ResourceCacheTest.cpp revision c0192e346ccdcacedb4d4f1f53a85caa29b97a6f
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);
52c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t srcSize = src.getSize();
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,
12311abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon                         ctxInfo) {
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
20485d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    GrBackendObject texHandles[2];
2056dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kW = 100;
2066dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kH = 100;
207672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
208091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon    texHandles[0] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig);
209091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon    texHandles[1] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig);
210672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
2116dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2126dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2137ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    GrBackendTexture backendTex1 = GrTest::CreateBackendTexture(context->contextPriv().getBackend(),
2147ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                kW,
2157ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                kH,
2167ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                kRGBA_8888_GrPixelConfig,
2177ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                texHandles[0]);
21832342f032e1dfd133040324f851f0365f9d4cb51Brian Osman    sk_sp<GrTexture> borrowed(context->resourceProvider()->wrapBackendTexture(
219b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips            backendTex1, kBorrow_GrWrapOwnership));
2207ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
2217ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel    GrBackendTexture backendTex2 = GrTest::CreateBackendTexture(context->contextPriv().getBackend(),
2227ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                kW,
2237ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                kH,
2247ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                kRGBA_8888_GrPixelConfig,
2257ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel                                                                texHandles[1]);
22632342f032e1dfd133040324f851f0365f9d4cb51Brian Osman    sk_sp<GrTexture> adopted(context->resourceProvider()->wrapBackendTexture(
227b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips            backendTex2, kAdopt_GrWrapOwnership));
2287ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
22985d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr);
23085d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    if (!borrowed || !adopted) {
2316dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
2326dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
2336dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
23496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    borrowed.reset(nullptr);
23596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    adopted.reset(nullptr);
2366dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2376dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->flush();
2386dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
239091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon    bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(texHandles[0]);
240091f60c2a0e4504c017b8a67ff96a0e829519b14bsalomon    bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(texHandles[1]);
2416dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2426dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, borrowedIsAlive);
2436dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, !adoptedIsAlive);
2446dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
24567d7620285cdfa60158add6615db03bd48e6d8b0bsalomon    gpu->deleteTestingOnlyBackendTexture(texHandles[0], !borrowedIsAlive);
24667d7620285cdfa60158add6615db03bd48e6d8b0bsalomon    gpu->deleteTestingOnlyBackendTexture(texHandles[1], !adoptedIsAlive);
2476dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2486dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2496dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon}
2506dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2516d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomonclass TestResource : public GrGpuResource {
2521c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    enum ScratchConstructor { kScratchConstructor };
253c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgpublic:
2546e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    static const size_t kDefaultSize = 100;
2555f939ab658a228dce34a3b14a545638407150b92mtklein
2561c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    /** Property that distinctly categorizes the resource.
2571c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon     * For example, textures have width, height, ... */
25823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
2591c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2602e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, SkBudgeted budgeted = SkBudgeted::kYes, size_t size = kDefaultSize)
2612e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
26296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
2631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(size)
2642e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(kA_SimulatedProperty)
2652e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(false) {
2665236cf480daf82b2f36e42795abdbbc915533a59bsalomon        ++fNumAlive;
2672e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCache(budgeted);
2685236cf480daf82b2f36e42795abdbbc915533a59bsalomon    }
2695236cf480daf82b2f36e42795abdbbc915533a59bsalomon
2702e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    static TestResource* CreateScratch(GrGpu* gpu, SkBudgeted budgeted,
2712e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                       SimulatedProperty property) {
2722e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        return new TestResource(gpu, budgeted, property, kScratchConstructor);
2738b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
2742e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    static TestResource* CreateWrapped(GrGpu* gpu, size_t size = kDefaultSize) {
2752e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        return new TestResource(gpu, size);
276c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
277c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
278d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~TestResource() override {
279334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon        --fNumAlive;
28071cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkSafeUnref(fToDelete);
281c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
282c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
28311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void setSize(size_t size) {
28411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        fSize = size;
28511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        this->didChangeGpuMemorySize();
28611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
28711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
288334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int NumAlive() { return fNumAlive; }
289c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
29071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setUnrefWhenDestroyed(TestResource* resource) {
29171cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkRefCnt_SafeAssign(fToDelete, resource);
292c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
293c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
2941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
2951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
2961c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
29724db3b1c35fb935660229da164fc5ad31977387fbsalomon        for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
29824db3b1c35fb935660229da164fc5ad31977387fbsalomon            builder[i] = static_cast<uint32_t>(i + property);
2991c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        }
3001c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
3011c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
3021c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static size_t ExpectedScratchKeySize() {
3031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
3041c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
305c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgprivate:
30624db3b1c35fb935660229da164fc5ad31977387fbsalomon    static const int kScratchKeyFieldCnt = 6;
3071c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
3082e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, SkBudgeted budgeted, SimulatedProperty property, ScratchConstructor)
3092e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
31096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
3111c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
3122e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(property)
3132e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(true) {
3141c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ++fNumAlive;
3152e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCache(budgeted);
3162e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    }
3172e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
3182e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    // Constructor for simulating resources that wrap backend objects.
3192e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, size_t size)
3202e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
3212e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fToDelete(nullptr)
3222e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fSize(size)
3232e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(kA_SimulatedProperty)
3242e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(false) {
3252e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        ++fNumAlive;
3262e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCacheWrapped();
3272e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    }
3282e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
3292e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    void computeScratchKey(GrScratchKey* key) const override {
3302e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        if (fIsScratch) {
3312e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            ComputeScratchKey(fProperty, key);
3322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        }
3331c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
3341c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
33536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t onGpuMemorySize() const override { return fSize; }
33669ed47f42d4877c178fdc0031cb01af2966ae235bsalomon
337c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    TestResource* fToDelete;
33811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    size_t fSize;
339334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int fNumAlive;
3401c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    SimulatedProperty fProperty;
3412e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    bool fIsScratch;
3426d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    typedef GrGpuResource INHERITED;
343c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org};
344334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonint TestResource::fNumAlive = 0;
345c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
346c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonclass Mock {
347c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonpublic:
348c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock(int maxCnt, size_t maxBytes) {
34902611d9afdd887ee443825ac88377f2eea093380Greg Daniel        fContext = GrContext::MakeMock(nullptr);
350c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        SkASSERT(fContext);
351c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext->setResourceCacheLimits(maxCnt, maxBytes);
3520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = fContext->getResourceCache();
3530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        cache->purgeAllUnlocked();
3540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
35571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
356c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
3570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache() { return fContext->getResourceCache(); }
358c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
359342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    GrContext* context() { return fContext.get(); }
360c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
361c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonprivate:
362342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrContext> fContext;
363c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon};
364c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
365c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_no_key(skiatest::Reporter* reporter) {
366c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
367c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
3680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
36971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
37071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Create a bunch of resources with no keys
371385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
372385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
373385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* c = new TestResource(context->getGpu());
374385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* d = new TestResource(context->getGpu());
37571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->setSize(11);
37671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->setSize(12);
37771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->setSize(13);
37871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->setSize(14);
37971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
38071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
3810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
38271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
3830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              d->gpuMemorySize() == cache->getResourceBytes());
38471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
38571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Should be safe to purge without deleting the resources since we still have refs.
3860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
38771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
38871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3898718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Since the resources have neither unique nor scratch keys, delete immediately upon unref.
39071cb0c241e439b6ed746b90294d0b6916644a644bsalomon
39171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->unref();
39271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
3930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
39471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
3950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
39671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
39771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->unref();
39871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
3990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
40071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
4010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
40271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
40371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->unref();
40471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
4050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
40771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
40871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->unref();
40971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
4100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
4110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
41271cb0c241e439b6ed746b90294d0b6916644a644bsalomon}
41371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
41424db3b1c35fb935660229da164fc5ad31977387fbsalomon// Each integer passed as a template param creates a new domain.
4151090da6433db575d59b93aec99f6bda49b808b84Brian Salomontemplate <int>
4161090da6433db575d59b93aec99f6bda49b808b84Brian Salomonstatic void make_unique_key(GrUniqueKey* key, int data, const char* tag = nullptr) {
4178718aafec239c93485e45bbe8fed19d9a8def079bsalomon    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
4181090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrUniqueKey::Builder builder(key, d, 1, tag);
41924db3b1c35fb935660229da164fc5ad31977387fbsalomon    builder[0] = data;
42024db3b1c35fb935660229da164fc5ad31977387fbsalomon}
42124db3b1c35fb935660229da164fc5ad31977387fbsalomon
42284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomonstatic void test_budgeting(skiatest::Reporter* reporter) {
423c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
424c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
4250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
426dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4278718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
4288718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
429dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4308718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create a scratch, a unique, and a wrapped resource
4311c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    TestResource* scratch =
4322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes, TestResource::kB_SimulatedProperty);
433dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(10);
434385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* unique = new TestResource(context->getGpu());
4358718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
436f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
4372e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* wrapped = TestResource::CreateWrapped(context->getGpu());
4385236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->setSize(12);
439385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* unbudgeted =
4402e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            new TestResource(context->getGpu(), SkBudgeted::kNo);
44184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->setSize(13);
442dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4430562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    // Make sure we can add a unique key to the wrapped resource
4448718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey2;
4458718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey2, 1);
446f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    wrapped->resourcePriv().setUniqueKey(uniqueKey2);
4470562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    GrGpuResource* wrappedViaKey = cache->findAndRefUniqueResource(uniqueKey2);
4480562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    REPORTER_ASSERT(reporter, wrappedViaKey != nullptr);
4490562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman
4500562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    // Remove the extra ref we just added.
4510562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    wrappedViaKey->unref();
452dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
453dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Make sure sizes are as we expect
4540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
4558718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
45684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
4570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4598718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
4600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
461ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
462dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
46363c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
4640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
4668718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
46784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
4680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4708718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
4710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
472ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
473dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
474dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Unreffing the wrapped resource should free it right away.
475dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
4760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
4778718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
4780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
479ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
480dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
48184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    // Now try freeing the budgeted resources first
4822e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    wrapped = TestResource::CreateWrapped(context->getGpu());
483dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(12);
4848718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
485ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 11 == cache->getPurgeableBytes());
4860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
48884c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
4890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
4900ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
4910ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes());
492ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
493dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
494dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->unref();
495ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 12 == cache->getPurgeableBytes());
4960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4970ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
49884c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
4990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
5000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
502ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
503dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
504dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
5050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes());
5070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
509ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
51084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
51184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->unref();
5120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
516ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
517dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon}
518dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
5195236cf480daf82b2f36e42795abdbbc915533a59bsalomonstatic void test_unbudgeted(skiatest::Reporter* reporter) {
520c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
521c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5220ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
5235236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5248718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
5258718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
5265236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5275236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* scratch;
5288718aafec239c93485e45bbe8fed19d9a8def079bsalomon    TestResource* unique;
5295236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* wrapped;
5305236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* unbudgeted;
5315236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5325236cf480daf82b2f36e42795abdbbc915533a59bsalomon    // A large uncached or wrapped resource shouldn't evict anything.
5332e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    scratch = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
5342e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                          TestResource::kB_SimulatedProperty);
5352e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
5365236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->setSize(10);
5375236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->unref();
5380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes());
5400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes());
542ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 10 == cache->getPurgeableBytes());
5435236cf480daf82b2f36e42795abdbbc915533a59bsalomon
544385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    unique = new TestResource(context->getGpu());
5458718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
546f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
5478718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
5480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5490ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
552ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5535236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    size_t large = 2 * cache->getResourceBytes();
5552e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    unbudgeted = new TestResource(context->getGpu(), SkBudgeted::kNo, large);
5560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
5580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
560ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5615236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5625236cf480daf82b2f36e42795abdbbc915533a59bsalomon    unbudgeted->unref();
5630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
567ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5685236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5692e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    wrapped = TestResource::CreateWrapped(context->getGpu(), large);
5700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
5720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
574ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5755236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5765236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->unref();
5770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
581ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
5820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon
5830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5840ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5850ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
588ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
5895236cf480daf82b2f36e42795abdbbc915533a59bsalomon}
5905236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5913582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon// This method can't be static because it needs to friended in GrGpuResource::CacheAccess.
5923582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomonvoid test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
5933582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon/*static*/ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
594c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
595c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
597c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
598c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* resource =
5992e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        TestResource::CreateScratch(context->getGpu(), SkBudgeted::kNo,
6002e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                    TestResource::kA_SimulatedProperty);
601c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrScratchKey key;
60223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
603c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
604c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    size_t size = resource->gpuMemorySize();
605c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    for (int i = 0; i < 2; ++i) {
606c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Since this resource is unbudgeted, it should not be reachable as scratch.
6073582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
608c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
6095ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        REPORTER_ASSERT(reporter, SkBudgeted::kNo == resource->resourcePriv().isBudgeted());
61096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
6110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
6140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
615ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
616c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
617c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Once it is unrefed, it should become available as scratch.
618c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        resource->unref();
6190ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6210ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
6220ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
623ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger        REPORTER_ASSERT(reporter, size == cache->getPurgeableBytes());
6246e83ac778f8f90939abe3aee3ea865428dff592frobertphillips        resource = static_cast<TestResource*>(cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
625c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource);
6263582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
627c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
6285ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
629c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
630c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        if (0 == i) {
6315f939ab658a228dce34a3b14a545638407150b92mtklein            // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
632c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // the above tests again.
6333582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().makeUnbudgeted();
634c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        } else {
635c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // After the second time around, try removing the scratch key
6363582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().removeScratchKey();
6370ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
6400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
641ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger            REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
6423582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid());
643c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
6445ec26ae9bfca635ccc98283aad5deda11519d826bsalomon            REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
645c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
646c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // now when it is unrefed it should die since it has no key.
647c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            resource->unref();
6480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
6490ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
6500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
6510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
652ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger            REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
653c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        }
6548b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
655c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon}
656c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
657c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
658c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
659c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
6600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
6618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
6628b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Create two resources that have the same scratch key.
66323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
6642e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                  SkBudgeted::kYes,
66523e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
66623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
6672e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                  SkBudgeted::kYes,
66823e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
6698b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
6708b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->setSize(12);
6711c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
67223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
6731c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Check for negative case consistency. (leaks upon test failure.)
67496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(scratchKey1, TestResource::kDefaultSize, 0));
6751c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6761c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
67723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
6781c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
680ac49acda520292b059bc37fd368dff912626c3d9bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
68371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
6840ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
6858b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
68663c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
6870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6888b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
6908b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
6918b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Unref but don't purge
6928b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->unref();
6938b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
6948b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6968b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
69763c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Purge again. This time resources should be purgeable.
6980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6998b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
7000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
7010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7028b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
7038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
70410e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_remove_scratch_key(skiatest::Reporter* reporter) {
705c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
706c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
70810e23caea3106be125acea10a637789e5a15c728bsalomon
70910e23caea3106be125acea10a637789e5a15c728bsalomon    // Create two resources that have the same scratch key.
7102e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
71123e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7122e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
71323e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
71410e23caea3106be125acea10a637789e5a15c728bsalomon    a->unref();
71510e23caea3106be125acea10a637789e5a15c728bsalomon    b->unref();
71610e23caea3106be125acea10a637789e5a15c728bsalomon
7171c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
7181c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
71923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
7201c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
72196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
7221c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
72423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
72510e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
7270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
72810e23caea3106be125acea10a637789e5a15c728bsalomon
72910e23caea3106be125acea10a637789e5a15c728bsalomon    // Find the first resource and remove its scratch key
73010e23caea3106be125acea10a637789e5a15c728bsalomon    GrGpuResource* find;
7316e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
7323582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
73310e23caea3106be125acea10a637789e5a15c728bsalomon    // It's still alive, but not cached by scratch key anymore
73410e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
7360ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
73710e23caea3106be125acea10a637789e5a15c728bsalomon
73810e23caea3106be125acea10a637789e5a15c728bsalomon    // The cache should immediately delete it when it's unrefed since it isn't accessible.
73910e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
74010e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
7410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
7420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
74310e23caea3106be125acea10a637789e5a15c728bsalomon
74410e23caea3106be125acea10a637789e5a15c728bsalomon    // Repeat for the second resource.
7456e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
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    // Should be able to call this multiple times with no problem.
7523582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
75310e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
7540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
75610e23caea3106be125acea10a637789e5a15c728bsalomon
75710e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
75810e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
7590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
76110e23caea3106be125acea10a637789e5a15c728bsalomon}
76210e23caea3106be125acea10a637789e5a15c728bsalomon
7631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomonstatic void test_scratch_key_consistency(skiatest::Reporter* reporter) {
764c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
765c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
7671c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7681c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Create two resources that have the same scratch key.
7692e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
77023e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7712e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
77223e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7731c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    a->unref();
7741c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    b->unref();
7751c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7761c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
7771c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key comparison and assignment is consistent.
7781c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
77923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
7801c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey2;
78123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
7821c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
7831c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
7841c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
7851c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey1;
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    scratchKey = scratchKey2;
7921c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
7931c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
7941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
7951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
7961c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
7971c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7981c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
79923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
8001c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
80196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
8021c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Find the first resource with a scratch key and a copy of a scratch key.
80423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
8056e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
80696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
8071c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
8081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8091c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey2 = scratchKey;
8106e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
81196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
8121c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find == a || find == b);
8131c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8146e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find2 = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
81596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find2 != nullptr);
8161c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 == a || find2 == b);
8171c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 != find);
8181c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find2->unref();
8191c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
8201c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon}
8211c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8228718aafec239c93485e45bbe8fed19d9a8def079bsalomonstatic void test_duplicate_unique_key(skiatest::Reporter* reporter) {
823c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
824c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
8250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
8268b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8278718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key;
8288718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key, 0);
8295f939ab658a228dce34a3b14a545638407150b92mtklein
8308718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create two resources that we will attempt to register with the same unique key.
831385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
8328b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
8335f939ab658a228dce34a3b14a545638407150b92mtklein
834f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Set key on resource a.
835f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
836f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
837f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
838f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
839f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Make sure that redundantly setting a's key works.
840f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
841f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
842f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
843f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
844f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache->getResourceBytes());
845f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
846f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
847f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Create resource b and set the same key. It should replace a's unique key cache entry.
848385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
849f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->setSize(12);
850f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->resourcePriv().setUniqueKey(key);
851f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b == cache->findAndRefUniqueResource(key));
852f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->unref();
85371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
854f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Still have two resources because a is still reffed.
8550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
856f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
8578b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8588b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
859f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
860f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now a should be gone.
861f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
862f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
863f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
864f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
865f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now replace b with c, but make sure c can start with one unique key and change it to b's key.
866f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Also make b be unreffed when replacement occurs.
8678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
868385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* c = new TestResource(context->getGpu());
869f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    GrUniqueKey differentKey;
870f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    make_unique_key<0>(&differentKey, 1);
871f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->setSize(13);
872f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(differentKey);
873f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
874f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() == cache->getResourceBytes());
875f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
876f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c replaces b and b should be immediately purged.
877f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(key);
8780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
879f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
88071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
88171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
882f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c shouldn't be purged because it is ref'ed.
8830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
8840ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
885f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
8868b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
8878b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
888f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Drop the ref on c, it should be kept alive because it has a unique key.
889f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
8900ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
891f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
89271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
89371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
894f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Verify that we can find c, then remove its unique key. It should get purged immediately.
895f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c == cache->findAndRefUniqueResource(key));
896f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().removeUniqueKey();
897f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
8980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
8990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
9008b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
90184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
90284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    {
90384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        GrUniqueKey key2;
90484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        make_unique_key<0>(&key2, 0);
905342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary        sk_sp<TestResource> d(new TestResource(context->getGpu()));
90684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        int foo = 4132;
90738d909ec2875f79952de08f36adfaac5680d2c53bungeman        key2.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
90884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        d->resourcePriv().setUniqueKey(key2);
90984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    }
91084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
91184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3;
91284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key3, 0);
913342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrGpuResource> d2(cache->findAndRefUniqueResource(key3));
91484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) d2->getUniqueKey().getCustomData()->data() == 4132);
9158b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
9168b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_purge_invalidated(skiatest::Reporter* reporter) {
918c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
919c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
9218b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2, key3;
9238718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
9248718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
9258718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key3, 3);
9265f939ab658a228dce34a3b14a545638407150b92mtklein
92723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Add three resources to the cache. Only c is usable as scratch.
928385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
929385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
9302e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource* c = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
93123e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kA_SimulatedProperty);
9328718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
9338718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
9348718aafec239c93485e45bbe8fed19d9a8def079bsalomon    c->resourcePriv().setUniqueKey(key3);
935c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    a->unref();
93623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // hold b until *after* the message is sent.
9378b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    c->unref();
938c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
9398718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
9408718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
9418718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
942334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
94323e619cf462b2a8a500f3ca750e099f79601f508bsalomon
9448718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef GrUniqueKeyInvalidatedMessage Msg;
9458718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkMessageBus<GrUniqueKeyInvalidatedMessage> Bus;
94623e619cf462b2a8a500f3ca750e099f79601f508bsalomon
94723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Invalidate two of the three, they should be purged and no longer accessible via their keys.
94823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key1));
94923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key2));
9500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
95123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // a should be deleted now, but we still have a ref on b.
9528718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
9538718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
95423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9558718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
9568b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9578b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Invalidate the third.
95823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key3));
9590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
96023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // we still have a ref on b, c should be recycled as scratch.
96123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9628718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key3));
96371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
96423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // make b purgeable. It should be immediately deleted since it has no key.
96523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    b->unref();
96623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
96723e619cf462b2a8a500f3ca750e099f79601f508bsalomon
96823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Make sure we actually get to c via it's scratch key, before we say goodbye.
96923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    GrScratchKey scratchKey;
97023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
9716e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
97223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, scratch == c);
97323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
97423e619cf462b2a8a500f3ca750e099f79601f508bsalomon
97523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Get rid of c.
9760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
9776e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
97871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
9790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
9800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
98123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, !scratch);
98223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
983c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org}
984c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
98571cb0c241e439b6ed746b90294d0b6916644a644bsalomonstatic void test_cache_chained_purge(skiatest::Reporter* reporter) {
986c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(3, 30000);
987c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9880ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
9898b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9908718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
9918718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
9928718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
993bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
994385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
995385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
9968718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
9978718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
99871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
999c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Make a cycle
1000c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->setUnrefWhenDestroyed(b);
1001c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->setUnrefWhenDestroyed(a);
1002334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
1003c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1004334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
1005c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->unref();
1006c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->unref();
10078b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
1008c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
10098b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
10100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
1011c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1012f21dab95405979a4aff9f6a741c818304a67f220bsalomon
1013c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Break the cycle
101496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    a->setUnrefWhenDestroyed(nullptr);
1015c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1016ac49acda520292b059bc37fd368dff912626c3d9bsalomon
10170ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
1018c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
1019bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org}
1020bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
10218b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_resource_size_changed(skiatest::Reporter* reporter) {
10228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
10238718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
10248718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
102511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
102611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test changing resources sizes (both increase & decrease).
102711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1028c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(3, 30000);
1029c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
10300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
103111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1032385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* a = new TestResource(context->getGpu());
10338718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
103411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
103511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1036385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* b = new TestResource(context->getGpu());
10378718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
103811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
103911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
10410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
10428b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
1043342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find2(
10448718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key2)));
10458b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(200);
1046342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find1(
10478718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key1)));
10488b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find1->setSize(50);
10498b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
105011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 250 == cache->getResourceBytes());
10520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
105311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
105411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
105511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test increasing a resources size beyond the cache budget.
105611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1057c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(2, 300);
1058c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
10590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
106011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1061385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* a = new TestResource(context->getGpu());
10628b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        a->setSize(100);
10638718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
106411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
106511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1066385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* b = new TestResource(context->getGpu());
10678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        b->setSize(100);
10688718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
106911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
107011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
10720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
107311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10748b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
1075342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find2(static_cast<TestResource*>(
10768718aafec239c93485e45bbe8fed19d9a8def079bsalomon                cache->findAndRefUniqueResource(key2)));
10778b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(201);
10788b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
10798718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
108011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 201 == cache->getResourceBytes());
10820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
108311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
108411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org}
108511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1086ddf30e64fe474847b204d7062fad3341d245062cbsalomonstatic void test_timestamp_wrap(skiatest::Reporter* reporter) {
1087ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kCount = 50;
1088ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetCnt = kCount / 2;
1089ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kLockedFreq = 8;
1090ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetSize = 0x80000000;
1091ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1092ddf30e64fe474847b204d7062fad3341d245062cbsalomon    SkRandom random;
1093ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1094ddf30e64fe474847b204d7062fad3341d245062cbsalomon    // Run the test 2*kCount times;
1095ddf30e64fe474847b204d7062fad3341d245062cbsalomon    for (int i = 0; i < 2 * kCount; ++i ) {
1096ddf30e64fe474847b204d7062fad3341d245062cbsalomon        Mock mock(kBudgetCnt, kBudgetSize);
1097ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrContext* context = mock.context();
1098ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrResourceCache* cache = mock.cache();
1099ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1100ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Pick a random number of resources to add before the timestamp will wrap.
1101ddf30e64fe474847b204d7062fad3341d245062cbsalomon        cache->changeTimestamp(SK_MaxU32 - random.nextULessThan(kCount + 1));
1102ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1103ddf30e64fe474847b204d7062fad3341d245062cbsalomon        static const int kNumToPurge = kCount - kBudgetCnt;
1104ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1105ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<int> shouldPurgeIdxs;
1106ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int purgeableCnt = 0;
1107ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<GrGpuResource*> resourcesToUnref;
1108ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1109ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Add kCount resources, holding onto resources at random so we have a mix of purgeable and
1110ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // unpurgeable resources.
1111ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1112ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1113ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1114ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1115385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
1116ddf30e64fe474847b204d7062fad3341d245062cbsalomon            r->resourcePriv().setUniqueKey(key);
1117ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (random.nextU() % kLockedFreq) {
1118ddf30e64fe474847b204d7062fad3341d245062cbsalomon                // Make this is purgeable.
1119ddf30e64fe474847b204d7062fad3341d245062cbsalomon                r->unref();
1120ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++purgeableCnt;
1121ddf30e64fe474847b204d7062fad3341d245062cbsalomon                if (purgeableCnt <= kNumToPurge) {
1122ddf30e64fe474847b204d7062fad3341d245062cbsalomon                    *shouldPurgeIdxs.append() = j;
1123ddf30e64fe474847b204d7062fad3341d245062cbsalomon                }
1124ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
1125ddf30e64fe474847b204d7062fad3341d245062cbsalomon                *resourcesToUnref.append() = r;
1126ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1127ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1128ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1129ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Verify that the correct resources were purged.
1130ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int currShouldPurgeIdx = 0;
1131ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1132ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1133ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1134ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrGpuResource* res = cache->findAndRefUniqueResource(key);
1135ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (currShouldPurgeIdx < shouldPurgeIdxs.count() &&
1136ddf30e64fe474847b204d7062fad3341d245062cbsalomon                shouldPurgeIdxs[currShouldPurgeIdx] == j) {
1137ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++currShouldPurgeIdx;
113896fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr == res);
1139ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
114096fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr != res);
1141ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1142ddf30e64fe474847b204d7062fad3341d245062cbsalomon            SkSafeUnref(res);
1143ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1144ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1145ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < resourcesToUnref.count(); ++j) {
1146ddf30e64fe474847b204d7062fad3341d245062cbsalomon            resourcesToUnref[j]->unref();
1147ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1148ddf30e64fe474847b204d7062fad3341d245062cbsalomon    }
1149ddf30e64fe474847b204d7062fad3341d245062cbsalomon}
1150ddf30e64fe474847b204d7062fad3341d245062cbsalomon
11513f324321cdd8fde7976d958e2888a1ec4e657e35bsalomonstatic void test_flush(skiatest::Reporter* reporter) {
11523f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    Mock mock(1000000, 1000000);
11533f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrContext* context = mock.context();
11543f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrResourceCache* cache = mock.cache();
11553f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11563f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // The current cache impl will round the max flush count to the next power of 2. So we choose a
11573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // power of two here to keep things simpler.
11583f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    static const int kFlushCount = 16;
11593f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    cache->setLimits(1000000, 1000000, kFlushCount);
11603f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11613f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
11623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Insert a resource and send a flush notification kFlushCount times.
11633f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1164385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
11653f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
11663f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
11673f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
11683f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->unref();
1169b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
11703f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11713f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Send flush notifications to the cache. Each flush should purge the oldest resource.
1173e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        for (int i = 0; i < kFlushCount; ++i) {
1174e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
11753f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount - i - 1 == cache->getResourceCount());
11763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            for (int j = 0; j < i; ++j) {
11773f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrUniqueKey k;
11783f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                make_unique_key<1>(&k, j);
11793f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrGpuResource* r = cache->findAndRefUniqueResource(k);
11803f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                REPORTER_ASSERT(reporter, !SkToBool(r));
11813f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                SkSafeUnref(r);
11823f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
11833f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11843f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11853f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
11863f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
11873f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
11883f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11893f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // Do a similar test but where we leave refs on some resources to prevent them from being
11903f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // purged.
11913f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
11923f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        GrGpuResource* refedResources[kFlushCount >> 1];
11933f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1194385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
11953f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
11963f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
11973f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
11983f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Leave a ref on every other resource, beginning with the first.
11993f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            if (SkToBool(i & 0x1)) {
12003f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                refedResources[i/2] = r;
12013f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            } else {
12023f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                r->unref();
12033f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
1204b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
12053f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12063f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12073f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
12083f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Should get a resource purged every other flush.
1209b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
1210e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon            REPORTER_ASSERT(reporter, kFlushCount - i/2 - 1 == cache->getResourceCount());
12113f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12123f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12133f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Unref all the resources that we kept refs on in the first loop.
12143f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount >> 1; ++i) {
12153f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            refedResources[i]->unref();
12163f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12173f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
1218e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        // After kFlushCount + 1 flushes they all will have sat in the purgeable queue for
1219e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        // kFlushCount full flushes.
1220e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        for (int i = 0; i < kFlushCount + 1; ++i) {
12213f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount >> 1 == cache->getResourceCount());
1222b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
12233f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12243f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
12253f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12263f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
12273f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
12283f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12293f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1230dc43898bbbd06202562514ae785116e0cc40f825bsalomon
1231dc43898bbbd06202562514ae785116e0cc40f825bsalomon    // Verify that calling flush() on a GrContext with nothing to do will not trigger resource
1232dc43898bbbd06202562514ae785116e0cc40f825bsalomon    // eviction.
1233dc43898bbbd06202562514ae785116e0cc40f825bsalomon    context->flush();
1234dc43898bbbd06202562514ae785116e0cc40f825bsalomon    for (int i = 0; i < 10; ++i) {
1235dc43898bbbd06202562514ae785116e0cc40f825bsalomon        TestResource* r = new TestResource(context->getGpu());
1236dc43898bbbd06202562514ae785116e0cc40f825bsalomon        GrUniqueKey k;
1237dc43898bbbd06202562514ae785116e0cc40f825bsalomon        make_unique_key<1>(&k, i);
1238dc43898bbbd06202562514ae785116e0cc40f825bsalomon        r->resourcePriv().setUniqueKey(k);
1239dc43898bbbd06202562514ae785116e0cc40f825bsalomon        r->unref();
1240dc43898bbbd06202562514ae785116e0cc40f825bsalomon    }
1241dc43898bbbd06202562514ae785116e0cc40f825bsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
1242dc43898bbbd06202562514ae785116e0cc40f825bsalomon    for (int i = 0; i < 10 * kFlushCount; ++i) {
1243dc43898bbbd06202562514ae785116e0cc40f825bsalomon        context->flush();
1244dc43898bbbd06202562514ae785116e0cc40f825bsalomon    }
1245dc43898bbbd06202562514ae785116e0cc40f825bsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
12463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon}
12473f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12485e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomonstatic void test_time_purge(skiatest::Reporter* reporter) {
12495e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    Mock mock(1000000, 1000000);
12505e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    GrContext* context = mock.context();
12515e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    GrResourceCache* cache = mock.cache();
12525e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12535e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    static constexpr int kCnts[] = {1, 10, 1024};
12545e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    auto nowish = []() {
12555e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // We sleep so that we ensure we get a value that is greater than the last call to
12565e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // GrStdSteadyClock::now().
12575e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::this_thread::sleep_for(GrStdSteadyClock::duration(5));
12585e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        auto result = GrStdSteadyClock::now();
12595e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Also sleep afterwards so we don't get this value again.
12605e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::this_thread::sleep_for(GrStdSteadyClock::duration(5));
12615e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        return result;
12625e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    };
12635e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12645e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    for (int cnt : kCnts) {
12655e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::unique_ptr<GrStdSteadyClock::time_point[]> timeStamps(
12665e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                new GrStdSteadyClock::time_point[cnt]);
12675e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        {
12685e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Insert resources and get time points between each addition.
12695e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
12705e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                TestResource* r = new TestResource(context->getGpu());
12715e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                GrUniqueKey k;
12725e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                make_unique_key<1>(&k, i);
12735e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->resourcePriv().setUniqueKey(k);
12745e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->unref();
12755e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                timeStamps.get()[i] = nowish();
12765e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
12775e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12785e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Purge based on the time points between resource additions. Each purge should remove
12795e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // the oldest resource.
12805e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
12815e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(timeStamps[i]);
12825e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt - i - 1 == cache->getResourceCount());
12835e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                for (int j = 0; j < i; ++j) {
12845e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    GrUniqueKey k;
12855e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    make_unique_key<1>(&k, j);
12865e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    GrGpuResource* r = cache->findAndRefUniqueResource(k);
12875e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    REPORTER_ASSERT(reporter, !SkToBool(r));
12885e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    SkSafeUnref(r);
12895e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                }
12905e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
12915e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12925e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
12935e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            cache->purgeAllUnlocked();
12945e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
12955e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
12965e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Do a similar test but where we leave refs on some resources to prevent them from being
12975e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // purged.
12985e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        {
12995e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            std::unique_ptr<GrGpuResource* []> refedResources(new GrGpuResource*[cnt / 2]);
13005e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
13015e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                TestResource* r = new TestResource(context->getGpu());
13025e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                GrUniqueKey k;
13035e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                make_unique_key<1>(&k, i);
13045e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->resourcePriv().setUniqueKey(k);
13055e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                // Leave a ref on every other resource, beginning with the first.
13065e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                if (SkToBool(i & 0x1)) {
13075e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    refedResources.get()[i / 2] = r;
13085e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                } else {
13095e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    r->unref();
13105e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                }
13115e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                timeStamps.get()[i] = nowish();
13125e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13135e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13145e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
13155e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                // Should get a resource purged every other frame.
13165e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(timeStamps[i]);
13175e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt - i / 2 - 1 == cache->getResourceCount());
13185e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13195e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13205e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Unref all the resources that we kept refs on in the first loop.
13215e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < (cnt / 2); ++i) {
13225e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                refedResources.get()[i]->unref();
13235e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(nowish());
13245e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt / 2 - i - 1 == cache->getResourceCount());
13255e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13265e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13275e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            cache->purgeAllUnlocked();
13285e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
13295e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13305e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
13315e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13325e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Verify that calling flush() on a GrContext with nothing to do will not trigger resource
13335e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // eviction
13345e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        context->flush();
13355e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        for (int i = 0; i < 10; ++i) {
13365e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            TestResource* r = new TestResource(context->getGpu());
13375e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            GrUniqueKey k;
13385e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            make_unique_key<1>(&k, i);
13395e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            r->resourcePriv().setUniqueKey(k);
13405e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            r->unref();
13415e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
13425e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
13435e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        context->flush();
13445e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
13455e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        cache->purgeResourcesNotUsedSince(nowish());
13465e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
13475e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    }
13485e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon}
13495e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13505480a18d8799511034d0da219c72932cd8f25274Derek Sollenbergerstatic void test_partial_purge(skiatest::Reporter* reporter) {
13515480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    Mock mock(6, 100);
13525480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    GrContext* context = mock.context();
13535480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    GrResourceCache* cache = mock.cache();
13545480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13555480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    enum TestsCase {
13565480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kOnlyScratch_TestCase = 0,
13575480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kPartialScratch_TestCase = 1,
13585480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kAllScratch_TestCase = 2,
13595480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kPartial_TestCase = 3,
13605480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kAll_TestCase = 4,
13615480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kNone_TestCase = 5,
13625480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kEndTests_TestCase = kNone_TestCase + 1
13635480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    };
13645480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13655480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    for (int testCase = 0; testCase < kEndTests_TestCase; testCase++) {
13665480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13675480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        GrUniqueKey key1, key2, key3;
13685480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key1, 1);
13695480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key2, 2);
13705480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key3, 3);
13715480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13725480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add three unique resources to the cache.
13735480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *unique1 = new TestResource(context->getGpu());
13745480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *unique2 = new TestResource(context->getGpu());
13755480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *unique3 = new TestResource(context->getGpu());
13765480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13775480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->resourcePriv().setUniqueKey(key1);
13785480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->resourcePriv().setUniqueKey(key2);
13795480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->resourcePriv().setUniqueKey(key3);
13805480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13815480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->setSize(10);
13825480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->setSize(11);
13835480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->setSize(12);
13845480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13855480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add two scratch resources to the cache.
13865480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *scratch1 = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
13875480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                                                             TestResource::kA_SimulatedProperty);
13885480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        TestResource *scratch2 = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
13895480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                                                             TestResource::kB_SimulatedProperty);
13905480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch1->setSize(13);
13915480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch2->setSize(14);
13925480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13935480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13945480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
13955480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
13965480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
13975480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
13985480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add resources to the purgeable queue
13995480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->unref();
14005480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch1->unref();
14015480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->unref();
14025480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch2->unref();
14035480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->unref();
14045480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14055480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
14065480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
14075480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
14085480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14095480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        switch(testCase) {
14105480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kOnlyScratch_TestCase: {
14115480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(14, true);
14125480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
14135480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 33 == cache->getBudgetedResourceBytes());
14145480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14155480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14165480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kPartialScratch_TestCase: {
14175480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(3, true);
14185480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 4 == cache->getBudgetedResourceCount());
14195480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 47 == cache->getBudgetedResourceBytes());
14205480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14215480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14225480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kAllScratch_TestCase: {
14235480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(50, true);
14245480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
14255480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
14265480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14275480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14285480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kPartial_TestCase: {
14295480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(13, false);
14305480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
14315480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 37 == cache->getBudgetedResourceBytes());
14325480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14335480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14345480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kAll_TestCase: {
14355480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(50, false);
14365480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
14375480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
14385480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14395480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14405480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kNone_TestCase: {
14415480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(0, true);
14425480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(0, false);
14435480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
14445480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
14455480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
14465480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
14475480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
14485480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        };
14495480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14505480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // ensure all are purged before the next
14515480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        context->purgeAllUnlockedResources();
14525480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
14535480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
14545480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14555480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    }
14565480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger}
14575480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
145810e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_large_resource_count(skiatest::Reporter* reporter) {
145910e23caea3106be125acea10a637789e5a15c728bsalomon    // Set the cache size to double the resource count because we're going to create 2x that number
146010e23caea3106be125acea10a637789e5a15c728bsalomon    // resources, using two different key domains. Add a little slop to the bytes because we resize
146110e23caea3106be125acea10a637789e5a15c728bsalomon    // down to 1 byte after creating the resource.
1462c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    static const int kResourceCnt = 2000;
146310e23caea3106be125acea10a637789e5a15c728bsalomon
1464c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
1465c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
14660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
146710e23caea3106be125acea10a637789e5a15c728bsalomon
146810e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
14698718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
14708718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
14718718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
147224db3b1c35fb935660229da164fc5ad31977387fbsalomon
147310e23caea3106be125acea10a637789e5a15c728bsalomon        TestResource* resource;
147410e23caea3106be125acea10a637789e5a15c728bsalomon
1475385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        resource = new TestResource(context->getGpu());
14768718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key1);
147710e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
147810e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
147910e23caea3106be125acea10a637789e5a15c728bsalomon
1480385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        resource = new TestResource(context->getGpu());
14818718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key2);
148210e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
148310e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
148410e23caea3106be125acea10a637789e5a15c728bsalomon    }
148510e23caea3106be125acea10a637789e5a15c728bsalomon
148610e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
1487ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 2 * kResourceCnt);
14880ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 2 * kResourceCnt);
14890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 2 * kResourceCnt);
14900ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 2 * kResourceCnt);
14910ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 2 * kResourceCnt);
149210e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
14938718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
14948718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
14958718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
149624db3b1c35fb935660229da164fc5ad31977387fbsalomon
14978718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
14988718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
149910e23caea3106be125acea10a637789e5a15c728bsalomon    }
150010e23caea3106be125acea10a637789e5a15c728bsalomon
15010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
150210e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
1503ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 0);
15040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 0);
15050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 0);
15060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 0);
15070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 0);
150810e23caea3106be125acea10a637789e5a15c728bsalomon
150910e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
15108718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
15118718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
15128718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
151324db3b1c35fb935660229da164fc5ad31977387fbsalomon
15148718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
15158718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
151610e23caea3106be125acea10a637789e5a15c728bsalomon    }
151710e23caea3106be125acea10a637789e5a15c728bsalomon}
151810e23caea3106be125acea10a637789e5a15c728bsalomon
151984cd621670a357484e1674e06d3d8d6f929a4ab2senorblancostatic void test_custom_data(skiatest::Reporter* reporter) {
152084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key1, key2;
152184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key1, 1);
152284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key2, 2);
152384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    int foo = 4132;
152438d909ec2875f79952de08f36adfaac5680d2c53bungeman    key1.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
152584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key1.getCustomData()->data() == 4132);
152684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, key2.getCustomData() == nullptr);
152784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
152884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    // Test that copying a key also takes a ref on its custom data.
152984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3 = key1;
153084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132);
153184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco}
153284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
1533c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomonstatic void test_abandoned(skiatest::Reporter* reporter) {
1534c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    Mock mock(10, 300);
1535c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrContext* context = mock.context();
1536342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrGpuResource> resource(new TestResource(context->getGpu()));
1537c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    context->abandonContext();
1538c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1539c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    REPORTER_ASSERT(reporter, resource->wasDestroyed());
1540c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1541c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    // Call all the public methods on resource in the abandoned state. They shouldn't crash.
1542c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
15438abb370aca280516f4861c6c942ec453aad018farobertphillips    resource->uniqueID();
1544c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getUniqueKey();
1545c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->wasDestroyed();
1546c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->gpuMemorySize();
1547c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getContext();
1548c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1549c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->abandon();
1550c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().getScratchKey();
1551c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().isBudgeted();
1552c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeBudgeted();
1553c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeUnbudgeted();
1554c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeScratchKey();
1555c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrUniqueKey key;
1556c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    make_unique_key<0>(&key, 1);
1557c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().setUniqueKey(key);
1558c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeUniqueKey();
1559c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon}
1560c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
15611090da6433db575d59b93aec99f6bda49b808b84Brian Salomonstatic void test_tags(skiatest::Reporter* reporter) {
15621090da6433db575d59b93aec99f6bda49b808b84Brian Salomon#ifdef SK_DEBUG
15631090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    // We will insert 1 resource with tag "tag1", 2 with "tag2", and so on, up through kLastTagIdx.
15641090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    static constexpr int kLastTagIdx = 10;
15651090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    static constexpr int kNumResources = kLastTagIdx * (kLastTagIdx + 1) / 2;
15661090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15671090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    Mock mock(kNumResources, kNumResources * TestResource::kDefaultSize);
15681090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrContext* context = mock.context();
15691090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrResourceCache* cache = mock.cache();
15701090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15711090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkString tagStr;
15721090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    int tagIdx = 0;
15731090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    int currTagCnt = 0;
15741090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15751090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    for (int i = 0; i < kNumResources; ++i, ++currTagCnt) {
15761090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        sk_sp<GrGpuResource> resource(new TestResource(context->getGpu()));
15771090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        GrUniqueKey key;
15781090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        if (currTagCnt == tagIdx) {
15791090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            tagIdx += 1;
15801090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            currTagCnt = 0;
15811090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            tagStr.printf("tag%d", tagIdx);
15821090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        }
15831090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        make_unique_key<1>(&key, i, tagStr.c_str());
15841090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        resource->resourcePriv().setUniqueKey(key);
15851090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    }
15861090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkASSERT(kLastTagIdx == tagIdx);
15871090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkASSERT(currTagCnt == kLastTagIdx);
15881090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15891090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    // Test i = 0 to exercise unused tag string.
15901090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    for (int i = 0; i <= kLastTagIdx; ++i) {
15911090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        tagStr.printf("tag%d", i);
15921090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        REPORTER_ASSERT(reporter, cache->countUniqueKeysWithTag(tagStr.c_str()) == i);
15931090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    }
15941090da6433db575d59b93aec99f6bda49b808b84Brian Salomon#endif
15951090da6433db575d59b93aec99f6bda49b808b84Brian Salomon}
15961090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
15971530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_GPUTEST(ResourceCacheMisc, reporter, factory) {
15988b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // The below tests create their own mock contexts.
159971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_no_key(reporter);
160084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    test_budgeting(reporter);
16015236cf480daf82b2f36e42795abdbbc915533a59bsalomon    test_unbudgeted(reporter);
1602c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    test_unbudgeted_to_scratch(reporter);
16038718aafec239c93485e45bbe8fed19d9a8def079bsalomon    test_duplicate_unique_key(reporter);
16048b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_duplicate_scratch_key(reporter);
160510e23caea3106be125acea10a637789e5a15c728bsalomon    test_remove_scratch_key(reporter);
16061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    test_scratch_key_consistency(reporter);
16078b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_purge_invalidated(reporter);
160871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_cache_chained_purge(reporter);
16098b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_resource_size_changed(reporter);
1610ddf30e64fe474847b204d7062fad3341d245062cbsalomon    test_timestamp_wrap(reporter);
16113f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    test_flush(reporter);
16125e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    test_time_purge(reporter);
16135480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    test_partial_purge(reporter);
161410e23caea3106be125acea10a637789e5a15c728bsalomon    test_large_resource_count(reporter);
161584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    test_custom_data(reporter);
1616c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    test_abandoned(reporter);
16171090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    test_tags(reporter);
1618c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
1619c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
1620d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips////////////////////////////////////////////////////////////////////////////////
162132342f032e1dfd133040324f851f0365f9d4cb51Brian Osmanstatic sk_sp<GrTexture> make_normal_texture(GrResourceProvider* provider,
1622d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            GrSurfaceFlags flags,
1623d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            int width, int height,
1624d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            int sampleCnt) {
1625d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrSurfaceDesc desc;
1626d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fFlags = flags;
1627b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1628d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fWidth = width;
1629d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fHeight = height;
1630d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
1631d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fSampleCnt = sampleCnt;
1632d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1633e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    return provider->createTexture(desc, SkBudgeted::kYes);
1634d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1635d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1636e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillipsstatic sk_sp<GrTextureProxy> make_mipmap_proxy(GrResourceProvider* provider,
1637e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               GrSurfaceFlags flags,
1638e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               int width, int height,
1639e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               int sampleCnt) {
1640d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    SkBitmap bm;
1641d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1642d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    bm.allocN32Pixels(width, height, true);
1643d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    bm.eraseColor(SK_ColorBLUE);
1644d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
16457b8400dad2f82dcc6ed3c7cc1707ebaf85f04840Brian Osman    sk_sp<SkMipMap> mipmaps(SkMipMap::Build(bm, SkDestinationSurfaceColorMode::kLegacy, nullptr));
1646d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    SkASSERT(mipmaps);
1647d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    SkASSERT(mipmaps->countLevels() > 1);
1648d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1649d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    int mipLevelCount = mipmaps->countLevels() + 1;
1650d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1651d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);
1652d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1653d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    texels[0].fPixels = bm.getPixels();
1654d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    texels[0].fRowBytes = bm.rowBytes();
1655d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1656d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    for (int i = 1; i < mipLevelCount; ++i) {
1657d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        SkMipMap::Level generatedMipLevel;
1658d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        mipmaps->getLevel(i - 1, &generatedMipLevel);
1659d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        texels[i].fPixels = generatedMipLevel.fPixmap.addr();
1660d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        texels[i].fRowBytes = generatedMipLevel.fPixmap.rowBytes();
1661d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    }
1662d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1663d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrSurfaceDesc desc;
1664d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fFlags = flags;
1665e44ef10ebbc7f64b627a9ac3a562bd87b3001b0cRobert Phillips    desc.fOrigin = (flags & kRenderTarget_GrSurfaceFlag) ? kBottomLeft_GrSurfaceOrigin
1666e44ef10ebbc7f64b627a9ac3a562bd87b3001b0cRobert Phillips                                                         : kTopLeft_GrSurfaceOrigin;
1667d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fWidth = width;
1668d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fHeight = height;
1669d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
1670d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fSampleCnt = sampleCnt;
167121918231b25037f6ae98a9a431d9e107e8b29f08Greg Daniel    desc.fIsMipMapped = true;
1672d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
16738e8c755f56e5dbaf0f87d88a775632010b32e974Robert Phillips    return GrSurfaceProxy::MakeDeferredMipMap(provider, desc, SkBudgeted::kYes,
16748e8c755f56e5dbaf0f87d88a775632010b32e974Robert Phillips                                              texels.get(), mipLevelCount);
1675d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1676d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1677d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips// Exercise GrSurface::gpuMemorySize for different combos of MSAA, RT-only,
1678d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips// Texture-only, both-RT-and-Texture and MIPmapped
1679d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert PhillipsDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) {
1680d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrContext* context = ctxInfo.grContext();
168132342f032e1dfd133040324f851f0365f9d4cb51Brian Osman    GrResourceProvider* provider = context->resourceProvider();
1682d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1683d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    static const int kSize = 64;
1684d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1685d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    // Normal versions
1686e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    {
1687e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        sk_sp<GrTexture> tex;
1688e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
1689e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
1690e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size_t size = tex->gpuMemorySize();
1691e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
1692e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
169381e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
169481e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        if (sampleCount >= 4) {
169581e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
169681e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                                      sampleCount);
1697e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            size = tex->gpuMemorySize();
169881e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            REPORTER_ASSERT(reporter,
169981e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4 == size ||                  // msaa4 failed
170081e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4*sampleCount == size ||      // auto-resolving
170181e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4*(sampleCount+1) == size);   // explicit resolve buffer
1702e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        }
1703d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1704e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        tex = make_normal_texture(provider, kNone_GrSurfaceFlags, kSize, kSize, 0);
1705d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        size = tex->gpuMemorySize();
1706e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
1707d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    }
1708d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1709d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1710d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    // Mipmapped versions
171148c9919335c7da6188c08a78552186760bd434eaBrian Osman    if (context->caps()->mipMapSupport()) {
1712e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        sk_sp<GrTextureProxy> proxy;
1713d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1714e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 0);
1715e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size_t size = proxy->gpuMemorySize();
1716e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
1717e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
171881e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig);
171981e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        if (sampleCount >= 4) {
172081e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
172181e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                                      sampleCount);
1722e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            size = proxy->gpuMemorySize();
1723e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            REPORTER_ASSERT(reporter,
172481e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4+(kSize*kSize*4)/3 == size ||                 // msaa4 failed
172581e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4*sampleCount+(kSize*kSize*4)/3 == size ||     // auto-resolving
172681e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4*(sampleCount+1)+(kSize*kSize*4)/3 == size);  // explicit resolve buffer
1727e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        }
17281b35256f1166358056b2aad8ce09caa6f07912d5Robert Phillips
1729e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        proxy = make_mipmap_proxy(provider, kNone_GrSurfaceFlags, kSize, kSize, 0);
1730e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size = proxy->gpuMemorySize();
1731e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
1732e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    }
1733d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1734d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1735c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#endif
1736