ResourceCacheTest.cpp revision d21b2a5d5c5dca87b7df02713782e722a2c0ae92
1c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org/*
2c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org * Copyright 2013 Google Inc.
3c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org *
4c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org * found in the LICENSE file.
6c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org */
7c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
83f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon// Include here to ensure SK_SUPPORT_GPU is set correctly before it is examined.
93f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon#include "SkTypes.h"
103f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#if SK_SUPPORT_GPU
125e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon#include <thread>
13bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "GrContext.h"
147ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel#include "GrContextPriv.h"
15c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#include "GrContextFactory.h"
16bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "GrGpu.h"
173582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourceCacheAccess.h"
183582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourcePriv.h"
19c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips#include "GrRenderTargetPriv.h"
200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#include "GrResourceCache.h"
21473addf17617d441edb44e501786cdd97d3ebdfbbsalomon#include "GrResourceProvider.h"
226dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon#include "GrTest.h"
23646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips#include "GrTexture.h"
24646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips
25bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "SkCanvas.h"
2671cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkGr.h"
2771cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkMessageBus.h"
28d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips#include "SkMipMap.h"
2969f6f00fd975823e825c5aa0b1b8f4416e7c812breed#include "SkSurface.h"
304ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
31c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
32c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gWidth = 640;
33c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gHeight = 480;
34c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
35c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
3668d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceCacheCache, reporter, ctxInfo) {
378b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    GrContext* context = ctxInfo.grContext();
381530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    GrSurfaceDesc desc;
39777b5633f599f2a99e2035fdb7ab600779ab95acBrian Osman    desc.fConfig = kRGBA_8888_GrPixelConfig;
401530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fFlags = kRenderTarget_GrSurfaceFlag;
411530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fWidth = gWidth;
421530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fHeight = gHeight;
431530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
44e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
451530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    SkCanvas* canvas = surface->getCanvas();
461530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
47c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
48c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
49c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap src;
50deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    src.allocN32Pixels(size.width(), size.height());
51c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    src.eraseColor(SK_ColorBLACK);
52f0ffb8943b7be477b769db23660a80013f3332ebMike Reed    size_t srcSize = src.computeByteSize();
53c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
5495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    size_t initialCacheSize;
5596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    context->getResourceCacheUsage(nullptr, &initialCacheSize);
56c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
57c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    int oldMaxNum;
58c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t oldMaxBytes;
5995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
6017f1ae63d57a3f3d3a0ae50e1b25b3f8b18fd328skia.committer@gmail.com
61c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // Set the cache limits so we can fit 10 "src" images and the
62c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // max number of textures doesn't matter
63c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t maxCacheSize = initialCacheSize + 10*srcSize;
6495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(1000, maxCacheSize);
65c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
66c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap readback;
67deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    readback.allocN32Pixels(size.width(), size.height());
68c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
69c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    for (int i = 0; i < 100; ++i) {
70c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        canvas->drawBitmap(src, 0, 0);
71f19421961c59ceabfb88a5c5cdf7c7e31a95b015Mike Reed        surface->readPixels(readback, 0, 0);
72c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
73c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // "modify" the src texture
74c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        src.notifyPixelsChanged();
75c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
7695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        size_t curCacheSize;
7796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        context->getResourceCacheUsage(nullptr, &curCacheSize);
78c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
79c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // we should never go over the size limit
80c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
81c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    }
82c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
8395c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
84c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
85c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
8611abd8d6cb2887bf66711863fb2dfe47da86d979bsalomonstatic bool is_rendering_and_not_angle_es3(sk_gpu_test::GrContextFactory::ContextType type) {
8711abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon    if (type == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES3_ContextType ||
8811abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon        type == sk_gpu_test::GrContextFactory::kANGLE_GL_ES3_ContextType) {
8911abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon        return false;
9011abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon    }
9111abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon    return sk_gpu_test::GrContextFactory::IsRenderingContext(type);
9211abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon}
9311abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon
94c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillipsstatic GrStencilAttachment* get_SB(GrRenderTarget* rt) {
95c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    return rt->renderTargetPriv().getStencilAttachment();
96c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips}
97c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
98c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillipsstatic sk_sp<GrRenderTarget> create_RT_with_SB(GrResourceProvider* provider,
99c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                               int size, int sampleCount, SkBudgeted budgeted) {
100c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    GrSurfaceDesc desc;
101c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fFlags = kRenderTarget_GrSurfaceFlag;
102c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
103c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fWidth = size;
104c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fHeight = size;
105c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
106c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fSampleCnt = sampleCount;
107c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
108c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    sk_sp<GrTexture> tex(provider->createTexture(desc, budgeted));
109c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    if (!tex || !tex->asRenderTarget()) {
110c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        return nullptr;
111c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    }
112c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
113c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    if (!provider->attachStencilAttachment(tex->asRenderTarget())) {
114c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        return nullptr;
115c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    }
116c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    SkASSERT(get_SB(tex->asRenderTarget()));
117c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
118c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    return sk_ref_sp(tex->asRenderTarget());
119c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips}
120c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
12111abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon// This currently fails on ES3 ANGLE contexts
12211abd8d6cb2887bf66711863fb2dfe47da86d979bsalomonDEF_GPUTEST_FOR_CONTEXTS(ResourceCacheStencilBuffers, &is_rendering_and_not_angle_es3, reporter,
123ec3253472947b0df618261479336a7b50b24f0c8Robert Phillips                         ctxInfo, nullptr) {
1248b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    GrContext* context = ctxInfo.grContext();
1255c77975e4c00e18e644c72b56f369858acd11b15Eric Karl    if (context->caps()->avoidStencilBuffers()) {
1265c77975e4c00e18e644c72b56f369858acd11b15Eric Karl        return;
1275c77975e4c00e18e644c72b56f369858acd11b15Eric Karl    }
1286bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
129c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    GrResourceProvider* provider = context->resourceProvider();
130c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
131c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    sk_sp<GrRenderTarget> smallRT0 = create_RT_with_SB(provider, 4, 0, SkBudgeted::kYes);
132c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    REPORTER_ASSERT(reporter, smallRT0);
133c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
134c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    {
135c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips       // Two budgeted RTs with the same desc should share a stencil buffer.
136c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        sk_sp<GrRenderTarget> smallRT1 = create_RT_with_SB(provider, 4, 0, SkBudgeted::kYes);
137c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, smallRT1);
138c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
139c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) == get_SB(smallRT1.get()));
1406bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
1416bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
142c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    {
143c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        // An unbudgeted RT with the same desc should also share.
144c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        sk_sp<GrRenderTarget> smallRT2 = create_RT_with_SB(provider, 4, 0, SkBudgeted::kNo);
145c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, smallRT2);
14602a44a488605112aa6683c9d919e13b188112ce1bsalomon
147c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) == get_SB(smallRT2.get()));
1486bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
149c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
150c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    {
151c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        // An RT with a much larger size should not share.
152c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        sk_sp<GrRenderTarget> bigRT = create_RT_with_SB(provider, 400, 0, SkBudgeted::kNo);
153c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, bigRT);
154c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
155c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) != get_SB(bigRT.get()));
1566bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
157c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
158c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    int smallSampleCount = context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
159c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    if (smallSampleCount > 0) {
1605f939ab658a228dce34a3b14a545638407150b92mtklein        // An RT with a different sample count should not share.
161c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        sk_sp<GrRenderTarget> smallMSAART0 = create_RT_with_SB(provider, 4, smallSampleCount,
162c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                                               SkBudgeted::kNo);
163b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#ifdef SK_BUILD_FOR_ANDROID
164b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        if (!smallMSAART0) {
165b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            // The nexus player seems to fail to create MSAA textures.
166b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            return;
167b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        }
168c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips#else
169c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, smallMSAART0);
170b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#endif
171c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
172c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) != get_SB(smallMSAART0.get()));
173c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
174c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        {
175c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            // A second MSAA RT should share with the first MSAA RT.
176c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            sk_sp<GrRenderTarget> smallMSAART1 = create_RT_with_SB(provider, 4, smallSampleCount,
177c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                                                   SkBudgeted::kNo);
178c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, smallMSAART1);
179c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
180c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, get_SB(smallMSAART0.get()) == get_SB(smallMSAART1.get()));
1816bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        }
182c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
18302a44a488605112aa6683c9d919e13b188112ce1bsalomon        // But not one with a larger sample count should not. (Also check that the request for 4
18402a44a488605112aa6683c9d919e13b188112ce1bsalomon        // samples didn't get rounded up to >= 8 or else they could share.).
185c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        int bigSampleCount = context->caps()->getSampleCount(8, kRGBA_8888_GrPixelConfig);
186c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        if (bigSampleCount != smallSampleCount) {
187c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            sk_sp<GrRenderTarget> smallMSAART2 = create_RT_with_SB(provider, 4, bigSampleCount,
188c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                                                   SkBudgeted::kNo);
189c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, smallMSAART2);
190c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
191c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, get_SB(smallMSAART0.get()) != get_SB(smallMSAART2.get()));
19202a44a488605112aa6683c9d919e13b188112ce1bsalomon        }
19302a44a488605112aa6683c9d919e13b188112ce1bsalomon    }
19402a44a488605112aa6683c9d919e13b188112ce1bsalomon}
19502a44a488605112aa6683c9d919e13b188112ce1bsalomon
19668d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceCacheWrappedResources, reporter, ctxInfo) {
1978b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    GrContext* context = ctxInfo.grContext();
198e63ffef6248bd103b5f7827f1e4bc75e47ca9e20bsalomon    GrGpu* gpu = context->getGpu();
199eeb8d99b4e58eb95cad3f7cd5438b9c2b3db7141jvanverth    // this test is only valid for GL
200eeb8d99b4e58eb95cad3f7cd5438b9c2b3db7141jvanverth    if (!gpu || !gpu->glContextForTesting()) {
2016dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
2026dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
2036dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
204d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    GrBackendTexture backendTextures[2];
2056dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kW = 100;
2066dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kH = 100;
207672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
208d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    backendTextures[0] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH,
209d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              kRGBA_8888_GrPixelConfig,
210d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              false, GrMipMapped::kNo);
211d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    backendTextures[1] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH,
212d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              kRGBA_8888_GrPixelConfig,
213d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              false, GrMipMapped::kNo);
214672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
2156dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2166dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
21732342f032e1dfd133040324f851f0365f9d4cb51Brian Osman    sk_sp<GrTexture> borrowed(context->resourceProvider()->wrapBackendTexture(
218d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips            backendTextures[0], kBorrow_GrWrapOwnership));
219d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips
22032342f032e1dfd133040324f851f0365f9d4cb51Brian Osman    sk_sp<GrTexture> adopted(context->resourceProvider()->wrapBackendTexture(
221d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips            backendTextures[1], kAdopt_GrWrapOwnership));
2227ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
22385d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr);
22485d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    if (!borrowed || !adopted) {
2256dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
2266dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
2276dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
22896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    borrowed.reset(nullptr);
22996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    adopted.reset(nullptr);
2306dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2316dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->flush();
2326dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
233d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(backendTextures[0]);
234d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(backendTextures[1]);
2356dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2366dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, borrowedIsAlive);
2376dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, !adoptedIsAlive);
2386dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
239d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    gpu->deleteTestingOnlyBackendTexture(&(backendTextures[0]), !borrowedIsAlive);
240d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    gpu->deleteTestingOnlyBackendTexture(&(backendTextures[1]), !adoptedIsAlive);
2416dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2426dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2436dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon}
2446dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2456d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomonclass TestResource : public GrGpuResource {
2461c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    enum ScratchConstructor { kScratchConstructor };
247c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgpublic:
2486e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    static const size_t kDefaultSize = 100;
2495f939ab658a228dce34a3b14a545638407150b92mtklein
2501c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    /** Property that distinctly categorizes the resource.
2511c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon     * For example, textures have width, height, ... */
25223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
2531c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2542e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, SkBudgeted budgeted = SkBudgeted::kYes, size_t size = kDefaultSize)
2552e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
25696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
2571c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(size)
2582e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(kA_SimulatedProperty)
2592e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(false) {
2605236cf480daf82b2f36e42795abdbbc915533a59bsalomon        ++fNumAlive;
2612e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCache(budgeted);
2625236cf480daf82b2f36e42795abdbbc915533a59bsalomon    }
2635236cf480daf82b2f36e42795abdbbc915533a59bsalomon
2642e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    static TestResource* CreateScratch(GrGpu* gpu, SkBudgeted budgeted,
2652e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                       SimulatedProperty property) {
2662e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        return new TestResource(gpu, budgeted, property, kScratchConstructor);
2678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
2682e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    static TestResource* CreateWrapped(GrGpu* gpu, size_t size = kDefaultSize) {
2692e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        return new TestResource(gpu, size);
270c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
271c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
272d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~TestResource() override {
273334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon        --fNumAlive;
27471cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkSafeUnref(fToDelete);
275c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
276c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
27711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void setSize(size_t size) {
27811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        fSize = size;
27911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        this->didChangeGpuMemorySize();
28011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
28111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
282334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int NumAlive() { return fNumAlive; }
283c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
28471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setUnrefWhenDestroyed(TestResource* resource) {
28571cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkRefCnt_SafeAssign(fToDelete, resource);
286c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
287c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
2881c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
2891c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
2901c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
29124db3b1c35fb935660229da164fc5ad31977387fbsalomon        for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
29224db3b1c35fb935660229da164fc5ad31977387fbsalomon            builder[i] = static_cast<uint32_t>(i + property);
2931c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        }
2941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
2951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2961c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static size_t ExpectedScratchKeySize() {
2971c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
2981c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
299c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgprivate:
30024db3b1c35fb935660229da164fc5ad31977387fbsalomon    static const int kScratchKeyFieldCnt = 6;
3011c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
3022e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, SkBudgeted budgeted, SimulatedProperty property, ScratchConstructor)
3032e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
30496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
3051c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
3062e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(property)
3072e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(true) {
3081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ++fNumAlive;
3092e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCache(budgeted);
3102e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    }
3112e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
3122e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    // Constructor for simulating resources that wrap backend objects.
3132e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, size_t size)
3142e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
3152e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fToDelete(nullptr)
3162e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fSize(size)
3172e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(kA_SimulatedProperty)
3182e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(false) {
3192e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        ++fNumAlive;
3202e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCacheWrapped();
3212e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    }
3222e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
3232e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    void computeScratchKey(GrScratchKey* key) const override {
3242e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        if (fIsScratch) {
3252e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            ComputeScratchKey(fProperty, key);
3262e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        }
3271c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
3281c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
32936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t onGpuMemorySize() const override { return fSize; }
33069ed47f42d4877c178fdc0031cb01af2966ae235bsalomon
331c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    TestResource* fToDelete;
33211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    size_t fSize;
333334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int fNumAlive;
3341c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    SimulatedProperty fProperty;
3352e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    bool fIsScratch;
3366d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    typedef GrGpuResource INHERITED;
337c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org};
338334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonint TestResource::fNumAlive = 0;
339c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
340c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonclass Mock {
341c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonpublic:
342c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock(int maxCnt, size_t maxBytes) {
34302611d9afdd887ee443825ac88377f2eea093380Greg Daniel        fContext = GrContext::MakeMock(nullptr);
344c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        SkASSERT(fContext);
345c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext->setResourceCacheLimits(maxCnt, maxBytes);
3460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = fContext->getResourceCache();
3470ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        cache->purgeAllUnlocked();
3480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
34971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
350c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
3510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache() { return fContext->getResourceCache(); }
352c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
353342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    GrContext* context() { return fContext.get(); }
354c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
355c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonprivate:
356342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrContext> fContext;
357c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon};
358c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
359c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_no_key(skiatest::Reporter* reporter) {
360c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
361c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
3620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
36371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
36471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Create a bunch of resources with no keys
365385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
366385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
367385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* c = new TestResource(context->getGpu());
368385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* d = new TestResource(context->getGpu());
36971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->setSize(11);
37071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->setSize(12);
37171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->setSize(13);
37271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->setSize(14);
37371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
37471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
3750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
37671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
3770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              d->gpuMemorySize() == cache->getResourceBytes());
37871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
37971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Should be safe to purge without deleting the resources since we still have refs.
3800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
38171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
38271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3838718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Since the resources have neither unique nor scratch keys, delete immediately upon unref.
38471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
38571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->unref();
38671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
3870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
38871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
3890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
39071cb0c241e439b6ed746b90294d0b6916644a644bsalomon
39171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->unref();
39271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
3930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
39471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
3950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
39671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
39771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->unref();
39871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
3990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
40171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
40271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->unref();
40371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
4040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
4050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
40671cb0c241e439b6ed746b90294d0b6916644a644bsalomon}
40771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
40824db3b1c35fb935660229da164fc5ad31977387fbsalomon// Each integer passed as a template param creates a new domain.
4091090da6433db575d59b93aec99f6bda49b808b84Brian Salomontemplate <int>
4101090da6433db575d59b93aec99f6bda49b808b84Brian Salomonstatic void make_unique_key(GrUniqueKey* key, int data, const char* tag = nullptr) {
4118718aafec239c93485e45bbe8fed19d9a8def079bsalomon    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
4121090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrUniqueKey::Builder builder(key, d, 1, tag);
41324db3b1c35fb935660229da164fc5ad31977387fbsalomon    builder[0] = data;
41424db3b1c35fb935660229da164fc5ad31977387fbsalomon}
41524db3b1c35fb935660229da164fc5ad31977387fbsalomon
41684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomonstatic void test_budgeting(skiatest::Reporter* reporter) {
417c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
418c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
4190ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
420dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4218718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
4228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
423dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4248718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create a scratch, a unique, and a wrapped resource
4251c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    TestResource* scratch =
4262e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes, TestResource::kB_SimulatedProperty);
427dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(10);
428385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* unique = new TestResource(context->getGpu());
4298718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
430f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
4312e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* wrapped = TestResource::CreateWrapped(context->getGpu());
4325236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->setSize(12);
433385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* unbudgeted =
4342e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            new TestResource(context->getGpu(), SkBudgeted::kNo);
43584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->setSize(13);
436dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4370562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    // Make sure we can add a unique key to the wrapped resource
4388718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey2;
4398718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey2, 1);
440f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    wrapped->resourcePriv().setUniqueKey(uniqueKey2);
4410562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    GrGpuResource* wrappedViaKey = cache->findAndRefUniqueResource(uniqueKey2);
4420562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    REPORTER_ASSERT(reporter, wrappedViaKey != nullptr);
4430562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman
4440562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    // Remove the extra ref we just added.
4450562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    wrappedViaKey->unref();
446dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
447dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Make sure sizes are as we expect
4480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
4498718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
45084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
4510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4538718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
4540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
455ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
456dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
45763c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
4580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
4608718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
46184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
4620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4648718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
4650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
466ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
467dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
468dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Unreffing the wrapped resource should free it right away.
469dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
4700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
4718718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
4720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
473ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
474dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
47584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    // Now try freeing the budgeted resources first
4762e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    wrapped = TestResource::CreateWrapped(context->getGpu());
477dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(12);
4788718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
479ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 11 == cache->getPurgeableBytes());
4800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
48284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
4830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
4840ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
4850ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes());
486ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
487dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
488dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->unref();
489ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 12 == cache->getPurgeableBytes());
4900ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4910ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
49284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
4930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
496ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
497dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
498dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
4990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes());
5010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5020ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
503ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
50484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
50584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->unref();
5060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5090ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
510ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
511dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon}
512dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
5135236cf480daf82b2f36e42795abdbbc915533a59bsalomonstatic void test_unbudgeted(skiatest::Reporter* reporter) {
514c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
515c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
5175236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
5198718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
5205236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5215236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* scratch;
5228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    TestResource* unique;
5235236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* wrapped;
5245236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* unbudgeted;
5255236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5265236cf480daf82b2f36e42795abdbbc915533a59bsalomon    // A large uncached or wrapped resource shouldn't evict anything.
5272e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    scratch = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
5282e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                          TestResource::kB_SimulatedProperty);
5292e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
5305236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->setSize(10);
5315236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->unref();
5320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes());
5340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes());
536ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 10 == cache->getPurgeableBytes());
5375236cf480daf82b2f36e42795abdbbc915533a59bsalomon
538385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    unique = new TestResource(context->getGpu());
5398718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
540f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
5418718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
5420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5440ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
546ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5475236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    size_t large = 2 * cache->getResourceBytes();
5492e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    unbudgeted = new TestResource(context->getGpu(), SkBudgeted::kNo, large);
5500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
5520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
554ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5555236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5565236cf480daf82b2f36e42795abdbbc915533a59bsalomon    unbudgeted->unref();
5570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
561ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5625236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5632e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    wrapped = TestResource::CreateWrapped(context->getGpu(), large);
5640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
5660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5670ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
568ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5695236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5705236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->unref();
5710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
575ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon
5770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
582ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
5835236cf480daf82b2f36e42795abdbbc915533a59bsalomon}
5845236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5853582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon// This method can't be static because it needs to friended in GrGpuResource::CacheAccess.
5863582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomonvoid test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
5873582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon/*static*/ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
588c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
589c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5900ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
591c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
592c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* resource =
5932e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        TestResource::CreateScratch(context->getGpu(), SkBudgeted::kNo,
5942e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                    TestResource::kA_SimulatedProperty);
595c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrScratchKey key;
59623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
597c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
598c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    size_t size = resource->gpuMemorySize();
599c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    for (int i = 0; i < 2; ++i) {
600c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Since this resource is unbudgeted, it should not be reachable as scratch.
6013582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
602c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
6035ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        REPORTER_ASSERT(reporter, SkBudgeted::kNo == resource->resourcePriv().isBudgeted());
60496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
6050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
6080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
609ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
610c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
611c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Once it is unrefed, it should become available as scratch.
612c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        resource->unref();
6130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
6160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
617ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger        REPORTER_ASSERT(reporter, size == cache->getPurgeableBytes());
6186e83ac778f8f90939abe3aee3ea865428dff592frobertphillips        resource = static_cast<TestResource*>(cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
619c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource);
6203582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
621c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
6225ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
623c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
624c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        if (0 == i) {
6255f939ab658a228dce34a3b14a545638407150b92mtklein            // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
626c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // the above tests again.
6273582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().makeUnbudgeted();
628c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        } else {
629c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // After the second time around, try removing the scratch key
6303582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().removeScratchKey();
6310ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
6340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
635ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger            REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
6363582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid());
637c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
6385ec26ae9bfca635ccc98283aad5deda11519d826bsalomon            REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
639c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
640c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // now when it is unrefed it should die since it has no key.
641c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            resource->unref();
6420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
6430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
6440ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
6450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
646ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger            REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
647c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        }
6488b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
649c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon}
650c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
651c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
652c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
653c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
6540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
6558b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
6568b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Create two resources that have the same scratch key.
65723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
6582e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                  SkBudgeted::kYes,
65923e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
66023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
6612e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                  SkBudgeted::kYes,
66223e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
6638b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
6648b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->setSize(12);
6651c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
66623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
6671c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Check for negative case consistency. (leaks upon test failure.)
66896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(scratchKey1, TestResource::kDefaultSize, 0));
6691c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6701c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
67123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
6721c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
674ac49acda520292b059bc37fd368dff912626c3d9bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
67771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
6780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
6798b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
68063c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
6810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6828b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
6848b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
6858b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Unref but don't purge
6868b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->unref();
6878b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
6888b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6908b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
69163c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Purge again. This time resources should be purgeable.
6920ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6938b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
6940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
6950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
6968b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
6978b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
69810e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_remove_scratch_key(skiatest::Reporter* reporter) {
699c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
700c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
70210e23caea3106be125acea10a637789e5a15c728bsalomon
70310e23caea3106be125acea10a637789e5a15c728bsalomon    // Create two resources that have the same scratch key.
7042e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
70523e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7062e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
70723e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
70810e23caea3106be125acea10a637789e5a15c728bsalomon    a->unref();
70910e23caea3106be125acea10a637789e5a15c728bsalomon    b->unref();
71010e23caea3106be125acea10a637789e5a15c728bsalomon
7111c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
7121c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
71323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
7141c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
71596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
7161c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7170ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
71823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
71910e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
7210ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
72210e23caea3106be125acea10a637789e5a15c728bsalomon
72310e23caea3106be125acea10a637789e5a15c728bsalomon    // Find the first resource and remove its scratch key
72410e23caea3106be125acea10a637789e5a15c728bsalomon    GrGpuResource* find;
7256e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
7263582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
72710e23caea3106be125acea10a637789e5a15c728bsalomon    // It's still alive, but not cached by scratch key anymore
72810e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
7300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
73110e23caea3106be125acea10a637789e5a15c728bsalomon
73210e23caea3106be125acea10a637789e5a15c728bsalomon    // The cache should immediately delete it when it's unrefed since it isn't accessible.
73310e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
73410e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
7350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
7360ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
73710e23caea3106be125acea10a637789e5a15c728bsalomon
73810e23caea3106be125acea10a637789e5a15c728bsalomon    // Repeat for the second resource.
7396e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
7403582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
74110e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
7420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
74410e23caea3106be125acea10a637789e5a15c728bsalomon
74510e23caea3106be125acea10a637789e5a15c728bsalomon    // Should be able to call this multiple times with no problem.
7463582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
74710e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
7480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7490ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
75010e23caea3106be125acea10a637789e5a15c728bsalomon
75110e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
75210e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
7530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
75510e23caea3106be125acea10a637789e5a15c728bsalomon}
75610e23caea3106be125acea10a637789e5a15c728bsalomon
7571c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomonstatic void test_scratch_key_consistency(skiatest::Reporter* reporter) {
758c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
759c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
7611c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7621c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Create two resources that have the same scratch key.
7632e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
76423e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7652e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
76623e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7671c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    a->unref();
7681c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    b->unref();
7691c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7701c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
7711c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key comparison and assignment is consistent.
7721c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
77323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
7741c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey2;
77523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
7761c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
7771c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
7781c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
7791c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey1;
7801c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
7811c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 == scratchKey);
7821c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey1);
7831c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey);
7841c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey2);
7851c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey2;
7861c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
7871c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
7881c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
7891c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
7901c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
7911c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7921c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
79323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
7941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
79596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
7961c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7971c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Find the first resource with a scratch key and a copy of a scratch key.
79823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
7996e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
80096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
8011c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
8021c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey2 = scratchKey;
8046e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
80596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
8061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find == a || find == b);
8071c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8086e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find2 = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
80996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find2 != nullptr);
8101c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 == a || find2 == b);
8111c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 != find);
8121c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find2->unref();
8131c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
8141c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon}
8151c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8168718aafec239c93485e45bbe8fed19d9a8def079bsalomonstatic void test_duplicate_unique_key(skiatest::Reporter* reporter) {
817c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
818c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
8190ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
8208b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8218718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key;
8228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key, 0);
8235f939ab658a228dce34a3b14a545638407150b92mtklein
8248718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create two resources that we will attempt to register with the same unique key.
825385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
8268b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
8275f939ab658a228dce34a3b14a545638407150b92mtklein
828f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Set key on resource a.
829f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
830f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
831f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
832f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
833f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Make sure that redundantly setting a's key works.
834f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
835f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
836f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
837f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
838f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache->getResourceBytes());
839f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
840f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
841f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Create resource b and set the same key. It should replace a's unique key cache entry.
842385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
843f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->setSize(12);
844f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->resourcePriv().setUniqueKey(key);
845f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b == cache->findAndRefUniqueResource(key));
846f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->unref();
84771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
848f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Still have two resources because a is still reffed.
8490ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
850f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
8518b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8528b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
853f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
854f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now a should be gone.
855f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
856f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
857f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
858f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
859f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now replace b with c, but make sure c can start with one unique key and change it to b's key.
860f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Also make b be unreffed when replacement occurs.
8618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
862385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* c = new TestResource(context->getGpu());
863f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    GrUniqueKey differentKey;
864f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    make_unique_key<0>(&differentKey, 1);
865f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->setSize(13);
866f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(differentKey);
867f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
868f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() == cache->getResourceBytes());
869f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
870f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c replaces b and b should be immediately purged.
871f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(key);
8720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
873f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
87471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
87571cb0c241e439b6ed746b90294d0b6916644a644bsalomon
876f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c shouldn't be purged because it is ref'ed.
8770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
8780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
879f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
8808b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
8818b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
882f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Drop the ref on c, it should be kept alive because it has a unique key.
883f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
8840ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
885f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
88671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
88771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
888f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Verify that we can find c, then remove its unique key. It should get purged immediately.
889f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c == cache->findAndRefUniqueResource(key));
890f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().removeUniqueKey();
891f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
8920ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
8930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
8948b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
89584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
89684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    {
89784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        GrUniqueKey key2;
89884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        make_unique_key<0>(&key2, 0);
899342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary        sk_sp<TestResource> d(new TestResource(context->getGpu()));
90084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        int foo = 4132;
90138d909ec2875f79952de08f36adfaac5680d2c53bungeman        key2.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
90284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        d->resourcePriv().setUniqueKey(key2);
90384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    }
90484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
90584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3;
90684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key3, 0);
907342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrGpuResource> d2(cache->findAndRefUniqueResource(key3));
90884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) d2->getUniqueKey().getCustomData()->data() == 4132);
9098b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
9108b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9118b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_purge_invalidated(skiatest::Reporter* reporter) {
912c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
913c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
9158b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9168718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2, key3;
9178718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
9188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
9198718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key3, 3);
9205f939ab658a228dce34a3b14a545638407150b92mtklein
92123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Add three resources to the cache. Only c is usable as scratch.
922385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
923385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
9242e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* c = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
92523e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kA_SimulatedProperty);
9268718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
9278718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
9288718aafec239c93485e45bbe8fed19d9a8def079bsalomon    c->resourcePriv().setUniqueKey(key3);
929c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    a->unref();
93023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // hold b until *after* the message is sent.
9318b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    c->unref();
932c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
9338718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
9348718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
9358718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
936334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
93723e619cf462b2a8a500f3ca750e099f79601f508bsalomon
9388718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef GrUniqueKeyInvalidatedMessage Msg;
9398718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkMessageBus<GrUniqueKeyInvalidatedMessage> Bus;
94023e619cf462b2a8a500f3ca750e099f79601f508bsalomon
94123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Invalidate two of the three, they should be purged and no longer accessible via their keys.
94223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key1));
94323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key2));
9440ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
94523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // a should be deleted now, but we still have a ref on b.
9468718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
9478718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
94823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9498718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
9508b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9518b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Invalidate the third.
95223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key3));
9530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
95423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // we still have a ref on b, c should be recycled as scratch.
95523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9568718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key3));
95771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
95823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // make b purgeable. It should be immediately deleted since it has no key.
95923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    b->unref();
96023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
96123e619cf462b2a8a500f3ca750e099f79601f508bsalomon
96223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Make sure we actually get to c via it's scratch key, before we say goodbye.
96323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    GrScratchKey scratchKey;
96423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
9656e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
96623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, scratch == c);
96723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
96823e619cf462b2a8a500f3ca750e099f79601f508bsalomon
96923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Get rid of c.
9700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
9716e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
97271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
9730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
9740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
97523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, !scratch);
97623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
977c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org}
978c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
97971cb0c241e439b6ed746b90294d0b6916644a644bsalomonstatic void test_cache_chained_purge(skiatest::Reporter* reporter) {
980c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(3, 30000);
981c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
9838b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9848718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
9858718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
9868718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
987bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
988385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
989385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
9908718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
9918718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
99271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
993c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Make a cycle
994c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->setUnrefWhenDestroyed(b);
995c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->setUnrefWhenDestroyed(a);
996334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
997c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
998334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
999c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->unref();
1000c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->unref();
10018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
1002c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
10038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
10040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
1005c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1006f21dab95405979a4aff9f6a741c818304a67f220bsalomon
1007c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Break the cycle
100896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    a->setUnrefWhenDestroyed(nullptr);
1009c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1010ac49acda520292b059bc37fd368dff912626c3d9bsalomon
10110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
1012c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
1013bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org}
1014bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
10158b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_resource_size_changed(skiatest::Reporter* reporter) {
10168718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
10178718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
10188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
101911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
102011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test changing resources sizes (both increase & decrease).
102111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1022c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(3, 30000);
1023c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
10240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
102511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1026385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* a = new TestResource(context->getGpu());
10278718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
102811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
102911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1030385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* b = new TestResource(context->getGpu());
10318718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
103211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
103311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
10350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
10368b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
1037342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find2(
10388718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key2)));
10398b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(200);
1040342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find1(
10418718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key1)));
10428b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find1->setSize(50);
10438b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
104411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 250 == cache->getResourceBytes());
10460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
104711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
104811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
104911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test increasing a resources size beyond the cache budget.
105011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1051c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(2, 300);
1052c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
10530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
105411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1055385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* a = new TestResource(context->getGpu());
10568b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        a->setSize(100);
10578718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
105811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
105911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1060385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* b = new TestResource(context->getGpu());
10618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        b->setSize(100);
10628718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
106311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
106411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
10660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
106711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10688b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
1069342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find2(static_cast<TestResource*>(
10708718aafec239c93485e45bbe8fed19d9a8def079bsalomon                cache->findAndRefUniqueResource(key2)));
10718b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(201);
10728b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
10738718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
107411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 201 == cache->getResourceBytes());
10760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
107711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
107811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org}
107911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1080ddf30e64fe474847b204d7062fad3341d245062cbsalomonstatic void test_timestamp_wrap(skiatest::Reporter* reporter) {
1081ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kCount = 50;
1082ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetCnt = kCount / 2;
1083ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kLockedFreq = 8;
1084ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetSize = 0x80000000;
1085ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1086ddf30e64fe474847b204d7062fad3341d245062cbsalomon    SkRandom random;
1087ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1088ddf30e64fe474847b204d7062fad3341d245062cbsalomon    // Run the test 2*kCount times;
1089ddf30e64fe474847b204d7062fad3341d245062cbsalomon    for (int i = 0; i < 2 * kCount; ++i ) {
1090ddf30e64fe474847b204d7062fad3341d245062cbsalomon        Mock mock(kBudgetCnt, kBudgetSize);
1091ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrContext* context = mock.context();
1092ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrResourceCache* cache = mock.cache();
1093ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1094ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Pick a random number of resources to add before the timestamp will wrap.
1095ddf30e64fe474847b204d7062fad3341d245062cbsalomon        cache->changeTimestamp(SK_MaxU32 - random.nextULessThan(kCount + 1));
1096ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1097ddf30e64fe474847b204d7062fad3341d245062cbsalomon        static const int kNumToPurge = kCount - kBudgetCnt;
1098ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1099ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<int> shouldPurgeIdxs;
1100ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int purgeableCnt = 0;
1101ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<GrGpuResource*> resourcesToUnref;
1102ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1103ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Add kCount resources, holding onto resources at random so we have a mix of purgeable and
1104ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // unpurgeable resources.
1105ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1106ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1107ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1108ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1109385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
1110ddf30e64fe474847b204d7062fad3341d245062cbsalomon            r->resourcePriv().setUniqueKey(key);
1111ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (random.nextU() % kLockedFreq) {
1112ddf30e64fe474847b204d7062fad3341d245062cbsalomon                // Make this is purgeable.
1113ddf30e64fe474847b204d7062fad3341d245062cbsalomon                r->unref();
1114ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++purgeableCnt;
1115ddf30e64fe474847b204d7062fad3341d245062cbsalomon                if (purgeableCnt <= kNumToPurge) {
1116ddf30e64fe474847b204d7062fad3341d245062cbsalomon                    *shouldPurgeIdxs.append() = j;
1117ddf30e64fe474847b204d7062fad3341d245062cbsalomon                }
1118ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
1119ddf30e64fe474847b204d7062fad3341d245062cbsalomon                *resourcesToUnref.append() = r;
1120ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1121ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1122ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1123ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Verify that the correct resources were purged.
1124ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int currShouldPurgeIdx = 0;
1125ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1126ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1127ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1128ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrGpuResource* res = cache->findAndRefUniqueResource(key);
1129ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (currShouldPurgeIdx < shouldPurgeIdxs.count() &&
1130ddf30e64fe474847b204d7062fad3341d245062cbsalomon                shouldPurgeIdxs[currShouldPurgeIdx] == j) {
1131ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++currShouldPurgeIdx;
113296fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr == res);
1133ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
113496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr != res);
1135ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1136ddf30e64fe474847b204d7062fad3341d245062cbsalomon            SkSafeUnref(res);
1137ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1138ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1139ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < resourcesToUnref.count(); ++j) {
1140ddf30e64fe474847b204d7062fad3341d245062cbsalomon            resourcesToUnref[j]->unref();
1141ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1142ddf30e64fe474847b204d7062fad3341d245062cbsalomon    }
1143ddf30e64fe474847b204d7062fad3341d245062cbsalomon}
1144ddf30e64fe474847b204d7062fad3341d245062cbsalomon
11453f324321cdd8fde7976d958e2888a1ec4e657e35bsalomonstatic void test_flush(skiatest::Reporter* reporter) {
11463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    Mock mock(1000000, 1000000);
11473f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrContext* context = mock.context();
11483f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrResourceCache* cache = mock.cache();
11493f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11503f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // The current cache impl will round the max flush count to the next power of 2. So we choose a
11513f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // power of two here to keep things simpler.
11523f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    static const int kFlushCount = 16;
11533f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    cache->setLimits(1000000, 1000000, kFlushCount);
11543f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11553f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
11563f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Insert a resource and send a flush notification kFlushCount times.
11573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1158385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
11593f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
11603f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
11613f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
11623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->unref();
1163b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
11643f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11653f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11663f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Send flush notifications to the cache. Each flush should purge the oldest resource.
1167e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        for (int i = 0; i < kFlushCount; ++i) {
1168e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
11693f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount - i - 1 == cache->getResourceCount());
11703f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            for (int j = 0; j < i; ++j) {
11713f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrUniqueKey k;
11723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                make_unique_key<1>(&k, j);
11733f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrGpuResource* r = cache->findAndRefUniqueResource(k);
11743f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                REPORTER_ASSERT(reporter, !SkToBool(r));
11753f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                SkSafeUnref(r);
11763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
11773f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11783f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11793f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
11803f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
11813f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
11823f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11833f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // Do a similar test but where we leave refs on some resources to prevent them from being
11843f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // purged.
11853f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
11863f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        GrGpuResource* refedResources[kFlushCount >> 1];
11873f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1188385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
11893f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
11903f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
11913f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
11923f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Leave a ref on every other resource, beginning with the first.
11933f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            if (SkToBool(i & 0x1)) {
11943f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                refedResources[i/2] = r;
11953f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            } else {
11963f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                r->unref();
11973f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
1198b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
11993f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12003f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12013f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
12023f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Should get a resource purged every other flush.
1203b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
1204e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon            REPORTER_ASSERT(reporter, kFlushCount - i/2 - 1 == cache->getResourceCount());
12053f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12063f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12073f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Unref all the resources that we kept refs on in the first loop.
12083f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount >> 1; ++i) {
12093f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            refedResources[i]->unref();
12103f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12113f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
1212e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        // After kFlushCount + 1 flushes they all will have sat in the purgeable queue for
1213e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        // kFlushCount full flushes.
1214e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        for (int i = 0; i < kFlushCount + 1; ++i) {
12153f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount >> 1 == cache->getResourceCount());
1216b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
12173f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12183f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
12193f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12203f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
12213f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
12223f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12233f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1224dc43898bbbd06202562514ae785116e0cc40f825bsalomon
1225dc43898bbbd06202562514ae785116e0cc40f825bsalomon    // Verify that calling flush() on a GrContext with nothing to do will not trigger resource
1226dc43898bbbd06202562514ae785116e0cc40f825bsalomon    // eviction.
1227dc43898bbbd06202562514ae785116e0cc40f825bsalomon    context->flush();
1228dc43898bbbd06202562514ae785116e0cc40f825bsalomon    for (int i = 0; i < 10; ++i) {
1229dc43898bbbd06202562514ae785116e0cc40f825bsalomon        TestResource* r = new TestResource(context->getGpu());
1230dc43898bbbd06202562514ae785116e0cc40f825bsalomon        GrUniqueKey k;
1231dc43898bbbd06202562514ae785116e0cc40f825bsalomon        make_unique_key<1>(&k, i);
1232dc43898bbbd06202562514ae785116e0cc40f825bsalomon        r->resourcePriv().setUniqueKey(k);
1233dc43898bbbd06202562514ae785116e0cc40f825bsalomon        r->unref();
1234dc43898bbbd06202562514ae785116e0cc40f825bsalomon    }
1235dc43898bbbd06202562514ae785116e0cc40f825bsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
1236dc43898bbbd06202562514ae785116e0cc40f825bsalomon    for (int i = 0; i < 10 * kFlushCount; ++i) {
1237dc43898bbbd06202562514ae785116e0cc40f825bsalomon        context->flush();
1238dc43898bbbd06202562514ae785116e0cc40f825bsalomon    }
1239dc43898bbbd06202562514ae785116e0cc40f825bsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
12403f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon}
12413f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12425e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomonstatic void test_time_purge(skiatest::Reporter* reporter) {
12435e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    Mock mock(1000000, 1000000);
12445e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    GrContext* context = mock.context();
12455e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    GrResourceCache* cache = mock.cache();
12465e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12475e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    static constexpr int kCnts[] = {1, 10, 1024};
12485e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    auto nowish = []() {
12495e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // We sleep so that we ensure we get a value that is greater than the last call to
12505e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // GrStdSteadyClock::now().
12515e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::this_thread::sleep_for(GrStdSteadyClock::duration(5));
12525e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        auto result = GrStdSteadyClock::now();
12535e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Also sleep afterwards so we don't get this value again.
12545e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::this_thread::sleep_for(GrStdSteadyClock::duration(5));
12555e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        return result;
12565e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    };
12575e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12585e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    for (int cnt : kCnts) {
12595e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::unique_ptr<GrStdSteadyClock::time_point[]> timeStamps(
12605e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                new GrStdSteadyClock::time_point[cnt]);
12615e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        {
12625e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Insert resources and get time points between each addition.
12635e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
12645e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                TestResource* r = new TestResource(context->getGpu());
12655e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                GrUniqueKey k;
12665e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                make_unique_key<1>(&k, i);
12675e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->resourcePriv().setUniqueKey(k);
12685e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->unref();
12695e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                timeStamps.get()[i] = nowish();
12705e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
12715e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12725e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Purge based on the time points between resource additions. Each purge should remove
12735e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // the oldest resource.
12745e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
12755e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(timeStamps[i]);
12765e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt - i - 1 == cache->getResourceCount());
12775e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                for (int j = 0; j < i; ++j) {
12785e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    GrUniqueKey k;
12795e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    make_unique_key<1>(&k, j);
12805e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    GrGpuResource* r = cache->findAndRefUniqueResource(k);
12815e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    REPORTER_ASSERT(reporter, !SkToBool(r));
12825e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    SkSafeUnref(r);
12835e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                }
12845e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
12855e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12865e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
12875e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            cache->purgeAllUnlocked();
12885e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
12895e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12905e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Do a similar test but where we leave refs on some resources to prevent them from being
12915e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // purged.
12925e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        {
12935e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            std::unique_ptr<GrGpuResource* []> refedResources(new GrGpuResource*[cnt / 2]);
12945e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
12955e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                TestResource* r = new TestResource(context->getGpu());
12965e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                GrUniqueKey k;
12975e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                make_unique_key<1>(&k, i);
12985e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->resourcePriv().setUniqueKey(k);
12995e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                // Leave a ref on every other resource, beginning with the first.
13005e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                if (SkToBool(i & 0x1)) {
13015e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    refedResources.get()[i / 2] = r;
13025e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                } else {
13035e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    r->unref();
13045e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                }
13055e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                timeStamps.get()[i] = nowish();
13065e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13075e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13085e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
13095e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                // Should get a resource purged every other frame.
13105e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(timeStamps[i]);
13115e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt - i / 2 - 1 == cache->getResourceCount());
13125e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13135e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13145e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Unref all the resources that we kept refs on in the first loop.
13155e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < (cnt / 2); ++i) {
13165e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                refedResources.get()[i]->unref();
13175e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(nowish());
13185e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt / 2 - i - 1 == cache->getResourceCount());
13195e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13205e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13215e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            cache->purgeAllUnlocked();
13225e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
13235e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13245e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
13255e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13265e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Verify that calling flush() on a GrContext with nothing to do will not trigger resource
13275e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // eviction
13285e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        context->flush();
13295e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        for (int i = 0; i < 10; ++i) {
13305e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            TestResource* r = new TestResource(context->getGpu());
13315e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            GrUniqueKey k;
13325e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            make_unique_key<1>(&k, i);
13335e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            r->resourcePriv().setUniqueKey(k);
13345e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            r->unref();
13355e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
13365e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
13375e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        context->flush();
13385e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
13395e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        cache->purgeResourcesNotUsedSince(nowish());
13405e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
13415e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    }
13425e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon}
13435e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13445480a18d8799511034d0da219c72932cd8f25274Derek Sollenbergerstatic void test_partial_purge(skiatest::Reporter* reporter) {
13455480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    Mock mock(6, 100);
13465480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    GrContext* context = mock.context();
13475480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    GrResourceCache* cache = mock.cache();
13485480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13495480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    enum TestsCase {
13505480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kOnlyScratch_TestCase = 0,
13515480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kPartialScratch_TestCase = 1,
13525480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kAllScratch_TestCase = 2,
13535480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kPartial_TestCase = 3,
13545480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kAll_TestCase = 4,
13555480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kNone_TestCase = 5,
13565480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kEndTests_TestCase = kNone_TestCase + 1
13575480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    };
13585480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13595480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    for (int testCase = 0; testCase < kEndTests_TestCase; testCase++) {
13605480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13615480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        GrUniqueKey key1, key2, key3;
13625480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key1, 1);
13635480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key2, 2);
13645480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key3, 3);
13655480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13665480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add three unique resources to the cache.
13675480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *unique1 = new TestResource(context->getGpu());
13685480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *unique2 = new TestResource(context->getGpu());
13695480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *unique3 = new TestResource(context->getGpu());
13705480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13715480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->resourcePriv().setUniqueKey(key1);
13725480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->resourcePriv().setUniqueKey(key2);
13735480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->resourcePriv().setUniqueKey(key3);
13745480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13755480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->setSize(10);
13765480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->setSize(11);
13775480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->setSize(12);
13785480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13795480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add two scratch resources to the cache.
13805480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *scratch1 = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
13815480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                                                             TestResource::kA_SimulatedProperty);
13825480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *scratch2 = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
13835480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                                                             TestResource::kB_SimulatedProperty);
13845480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch1->setSize(13);
13855480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch2->setSize(14);
13865480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13875480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13885480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
13895480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
13905480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
13915480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13925480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add resources to the purgeable queue
13935480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->unref();
13945480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch1->unref();
13955480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->unref();
13965480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch2->unref();
13975480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->unref();
13985480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13995480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
14005480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
14015480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
14025480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14035480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        switch(testCase) {
14045480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kOnlyScratch_TestCase: {
14055480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(14, true);
14065480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
14075480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 33 == cache->getBudgetedResourceBytes());
14085480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14095480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14105480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kPartialScratch_TestCase: {
14115480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(3, true);
14125480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 4 == cache->getBudgetedResourceCount());
14135480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 47 == cache->getBudgetedResourceBytes());
14145480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14155480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14165480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kAllScratch_TestCase: {
14175480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(50, true);
14185480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
14195480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
14205480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14215480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14225480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kPartial_TestCase: {
14235480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(13, false);
14245480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
14255480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 37 == cache->getBudgetedResourceBytes());
14265480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14275480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14285480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kAll_TestCase: {
14295480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(50, false);
14305480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
14315480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
14325480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14335480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14345480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kNone_TestCase: {
14355480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(0, true);
14365480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(0, false);
14375480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
14385480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
14395480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
14405480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14415480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14425480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        };
14435480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14445480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // ensure all are purged before the next
14455480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        context->purgeAllUnlockedResources();
14465480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
14475480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
14485480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14495480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    }
14505480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger}
14515480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
145210e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_large_resource_count(skiatest::Reporter* reporter) {
145310e23caea3106be125acea10a637789e5a15c728bsalomon    // Set the cache size to double the resource count because we're going to create 2x that number
145410e23caea3106be125acea10a637789e5a15c728bsalomon    // resources, using two different key domains. Add a little slop to the bytes because we resize
145510e23caea3106be125acea10a637789e5a15c728bsalomon    // down to 1 byte after creating the resource.
1456c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    static const int kResourceCnt = 2000;
145710e23caea3106be125acea10a637789e5a15c728bsalomon
1458c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
1459c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
14600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
146110e23caea3106be125acea10a637789e5a15c728bsalomon
146210e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
14638718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
14648718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
14658718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
146624db3b1c35fb935660229da164fc5ad31977387fbsalomon
146710e23caea3106be125acea10a637789e5a15c728bsalomon        TestResource* resource;
146810e23caea3106be125acea10a637789e5a15c728bsalomon
1469385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        resource = new TestResource(context->getGpu());
14708718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key1);
147110e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
147210e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
147310e23caea3106be125acea10a637789e5a15c728bsalomon
1474385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        resource = new TestResource(context->getGpu());
14758718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key2);
147610e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
147710e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
147810e23caea3106be125acea10a637789e5a15c728bsalomon    }
147910e23caea3106be125acea10a637789e5a15c728bsalomon
148010e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
1481ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 2 * kResourceCnt);
14820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 2 * kResourceCnt);
14830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 2 * kResourceCnt);
14840ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 2 * kResourceCnt);
14850ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 2 * kResourceCnt);
148610e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
14878718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
14888718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
14898718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
149024db3b1c35fb935660229da164fc5ad31977387fbsalomon
14918718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
14928718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
149310e23caea3106be125acea10a637789e5a15c728bsalomon    }
149410e23caea3106be125acea10a637789e5a15c728bsalomon
14950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
149610e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
1497ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 0);
14980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 0);
14990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 0);
15000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 0);
15010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 0);
150210e23caea3106be125acea10a637789e5a15c728bsalomon
150310e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
15048718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
15058718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
15068718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
150724db3b1c35fb935660229da164fc5ad31977387fbsalomon
15088718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
15098718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
151010e23caea3106be125acea10a637789e5a15c728bsalomon    }
151110e23caea3106be125acea10a637789e5a15c728bsalomon}
151210e23caea3106be125acea10a637789e5a15c728bsalomon
151384cd621670a357484e1674e06d3d8d6f929a4ab2senorblancostatic void test_custom_data(skiatest::Reporter* reporter) {
151484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key1, key2;
151584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key1, 1);
151684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key2, 2);
151784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    int foo = 4132;
151838d909ec2875f79952de08f36adfaac5680d2c53bungeman    key1.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
151984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key1.getCustomData()->data() == 4132);
152084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, key2.getCustomData() == nullptr);
152184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
152284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    // Test that copying a key also takes a ref on its custom data.
152384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3 = key1;
152484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132);
152584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco}
152684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
1527c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomonstatic void test_abandoned(skiatest::Reporter* reporter) {
1528c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    Mock mock(10, 300);
1529c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrContext* context = mock.context();
1530342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrGpuResource> resource(new TestResource(context->getGpu()));
1531c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    context->abandonContext();
1532c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1533c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    REPORTER_ASSERT(reporter, resource->wasDestroyed());
1534c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1535c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    // Call all the public methods on resource in the abandoned state. They shouldn't crash.
1536c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
15378abb370aca280516f4861c6c942ec453aad018farobertphillips    resource->uniqueID();
1538c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getUniqueKey();
1539c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->wasDestroyed();
1540c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->gpuMemorySize();
1541c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getContext();
1542c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1543c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->abandon();
1544c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().getScratchKey();
1545c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().isBudgeted();
1546c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeBudgeted();
1547c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeUnbudgeted();
1548c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeScratchKey();
1549c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrUniqueKey key;
1550c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    make_unique_key<0>(&key, 1);
1551c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().setUniqueKey(key);
1552c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeUniqueKey();
1553c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon}
1554c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
15551090da6433db575d59b93aec99f6bda49b808b84Brian Salomonstatic void test_tags(skiatest::Reporter* reporter) {
15561090da6433db575d59b93aec99f6bda49b808b84Brian Salomon#ifdef SK_DEBUG
15571090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    // We will insert 1 resource with tag "tag1", 2 with "tag2", and so on, up through kLastTagIdx.
15581090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    static constexpr int kLastTagIdx = 10;
15591090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    static constexpr int kNumResources = kLastTagIdx * (kLastTagIdx + 1) / 2;
15601090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15611090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    Mock mock(kNumResources, kNumResources * TestResource::kDefaultSize);
15621090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrContext* context = mock.context();
15631090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrResourceCache* cache = mock.cache();
15641090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15651090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkString tagStr;
15661090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    int tagIdx = 0;
15671090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    int currTagCnt = 0;
15681090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15691090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    for (int i = 0; i < kNumResources; ++i, ++currTagCnt) {
15701090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        sk_sp<GrGpuResource> resource(new TestResource(context->getGpu()));
15711090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        GrUniqueKey key;
15721090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        if (currTagCnt == tagIdx) {
15731090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            tagIdx += 1;
15741090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            currTagCnt = 0;
15751090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            tagStr.printf("tag%d", tagIdx);
15761090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        }
15771090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        make_unique_key<1>(&key, i, tagStr.c_str());
15781090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        resource->resourcePriv().setUniqueKey(key);
15791090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    }
15801090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkASSERT(kLastTagIdx == tagIdx);
15811090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkASSERT(currTagCnt == kLastTagIdx);
15821090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15831090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    // Test i = 0 to exercise unused tag string.
15841090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    for (int i = 0; i <= kLastTagIdx; ++i) {
15851090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        tagStr.printf("tag%d", i);
15861090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        REPORTER_ASSERT(reporter, cache->countUniqueKeysWithTag(tagStr.c_str()) == i);
15871090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    }
15881090da6433db575d59b93aec99f6bda49b808b84Brian Salomon#endif
15891090da6433db575d59b93aec99f6bda49b808b84Brian Salomon}
15901090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
1591dcfca431e3c350e17eedb3402cc63577cea8d4eaBrian SalomonDEF_GPUTEST(ResourceCacheMisc, reporter, /* options */) {
15928b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // The below tests create their own mock contexts.
159371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_no_key(reporter);
159484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    test_budgeting(reporter);
15955236cf480daf82b2f36e42795abdbbc915533a59bsalomon    test_unbudgeted(reporter);
1596c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    test_unbudgeted_to_scratch(reporter);
15978718aafec239c93485e45bbe8fed19d9a8def079bsalomon    test_duplicate_unique_key(reporter);
15988b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_duplicate_scratch_key(reporter);
159910e23caea3106be125acea10a637789e5a15c728bsalomon    test_remove_scratch_key(reporter);
16001c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    test_scratch_key_consistency(reporter);
16018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_purge_invalidated(reporter);
160271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_cache_chained_purge(reporter);
16038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_resource_size_changed(reporter);
1604ddf30e64fe474847b204d7062fad3341d245062cbsalomon    test_timestamp_wrap(reporter);
16053f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    test_flush(reporter);
16065e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    test_time_purge(reporter);
16075480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    test_partial_purge(reporter);
160810e23caea3106be125acea10a637789e5a15c728bsalomon    test_large_resource_count(reporter);
160984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    test_custom_data(reporter);
1610c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    test_abandoned(reporter);
16111090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    test_tags(reporter);
1612c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
1613c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
1614d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips////////////////////////////////////////////////////////////////////////////////
161532342f032e1dfd133040324f851f0365f9d4cb51Brian Osmanstatic sk_sp<GrTexture> make_normal_texture(GrResourceProvider* provider,
1616d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            GrSurfaceFlags flags,
1617d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            int width, int height,
1618d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            int sampleCnt) {
1619d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrSurfaceDesc desc;
1620d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fFlags = flags;
1621b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1622d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fWidth = width;
1623d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fHeight = height;
1624d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
1625d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fSampleCnt = sampleCnt;
1626d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1627e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    return provider->createTexture(desc, SkBudgeted::kYes);
1628d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1629d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1630e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillipsstatic sk_sp<GrTextureProxy> make_mipmap_proxy(GrResourceProvider* provider,
1631e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               GrSurfaceFlags flags,
1632e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               int width, int height,
1633e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               int sampleCnt) {
1634d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    SkBitmap bm;
1635d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1636d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    bm.allocN32Pixels(width, height, true);
1637d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    bm.eraseColor(SK_ColorBLUE);
1638d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
16397b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    sk_sp<SkMipMap> mipmaps(SkMipMap::Build(bm, SkDestinationSurfaceColorMode::kLegacy, nullptr));
1640d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    SkASSERT(mipmaps);
1641d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    SkASSERT(mipmaps->countLevels() > 1);
1642d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1643d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    int mipLevelCount = mipmaps->countLevels() + 1;
1644d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1645d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
1646d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1647d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    texels[0].fPixels = bm.getPixels();
1648d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    texels[0].fRowBytes = bm.rowBytes();
1649d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1650d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    for (int i = 1; i < mipLevelCount; ++i) {
1651d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        SkMipMap::Level generatedMipLevel;
1652d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        mipmaps->getLevel(i - 1, &generatedMipLevel);
1653d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        texels[i].fPixels = generatedMipLevel.fPixmap.addr();
1654d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
1655d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    }
1656d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1657d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrSurfaceDesc desc;
1658d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fFlags = flags;
1659e44ef10ebbc7f64b627a9ac3a562bd87b3001b0cRobert Phillips    desc.fOrigin = (flags & kRenderTarget_GrSurfaceFlag) ? kBottomLeft_GrSurfaceOrigin
1660e44ef10ebbc7f64b627a9ac3a562bd87b3001b0cRobert Phillips                                                         : kTopLeft_GrSurfaceOrigin;
1661d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fWidth = width;
1662d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fHeight = height;
1663d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
1664d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fSampleCnt = sampleCnt;
1665d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
16668e8c755f56e5dbaf0f87d88a775632010b32e974Robert Phillips    return GrSurfaceProxy::MakeDeferredMipMap(provider, desc, SkBudgeted::kYes,
16678e8c755f56e5dbaf0f87d88a775632010b32e974Robert Phillips                                              texels.get(), mipLevelCount);
1668d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1669d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1670d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips// Exercise GrSurface::gpuMemorySize for different combos of MSAA, RT-only,
1671d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips// Texture-only, both-RT-and-Texture and MIPmapped
1672d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert PhillipsDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) {
1673d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrContext* context = ctxInfo.grContext();
167432342f032e1dfd133040324f851f0365f9d4cb51Brian Osman    GrResourceProvider* provider = context->resourceProvider();
1675d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1676d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    static const int kSize = 64;
1677d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1678d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    // Normal versions
1679e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    {
1680e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        sk_sp<GrTexture> tex;
1681e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
1682e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
1683e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size_t size = tex->gpuMemorySize();
1684e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
1685e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
168681e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
168781e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        if (sampleCount >= 4) {
168881e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
168981e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                                      sampleCount);
1690e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            size = tex->gpuMemorySize();
169181e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            REPORTER_ASSERT(reporter,
169281e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4 == size ||                  // msaa4 failed
169381e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4*sampleCount == size ||      // auto-resolving
169481e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4*(sampleCount+1) == size);   // explicit resolve buffer
1695e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        }
1696d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1697e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        tex = make_normal_texture(provider, kNone_GrSurfaceFlags, kSize, kSize, 0);
1698d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        size = tex->gpuMemorySize();
1699e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
1700d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    }
1701d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1702d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1703d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    // Mipmapped versions
170448c9919335c7da6188c08a78552186760bd434eaBrian Osman    if (context->caps()->mipMapSupport()) {
1705e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        sk_sp<GrTextureProxy> proxy;
1706d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1707e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
1708e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size_t size = proxy->gpuMemorySize();
1709e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
1710e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
171181e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
171281e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        if (sampleCount >= 4) {
171381e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
171481e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                                      sampleCount);
1715e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            size = proxy->gpuMemorySize();
1716e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            REPORTER_ASSERT(reporter,
171781e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4+(kSize*kSize*4)/3 == size ||                 // msaa4 failed
171881e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4*sampleCount+(kSize*kSize*4)/3 == size ||     // auto-resolving
171981e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4*(sampleCount+1)+(kSize*kSize*4)/3 == size);  // explicit resolve buffer
1720e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        }
17211b35256f1166358056b2aad8ce09caa6f07912d5Robert Phillips
1722e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        proxy = make_mipmap_proxy(provider, kNone_GrSurfaceFlags, kSize, kSize, 0);
1723e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size = proxy->gpuMemorySize();
1724e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
1725e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    }
1726d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1727d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1728c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#endif
1729