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"
190bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillips#include "GrProxyProvider.h"
20c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips#include "GrRenderTargetPriv.h"
210ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#include "GrResourceCache.h"
22473addf17617d441edb44e501786cdd97d3ebdfbbsalomon#include "GrResourceProvider.h"
236dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon#include "GrTest.h"
24646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips#include "GrTexture.h"
25646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips
26bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "SkCanvas.h"
2771cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkGr.h"
2871cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkMessageBus.h"
29d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips#include "SkMipMap.h"
3069f6f00fd975823e825c5aa0b1b8f4416e7c812breed#include "SkSurface.h"
314ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
32c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
33c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gWidth = 640;
34c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gHeight = 480;
35c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
36c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
3768d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceCacheCache, reporter, ctxInfo) {
388b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    GrContext* context = ctxInfo.grContext();
391530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    GrSurfaceDesc desc;
40777b5633f599f2a99e2035fdb7ab600779ab95acBrian Osman    desc.fConfig = kRGBA_8888_GrPixelConfig;
411530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fFlags = kRenderTarget_GrSurfaceFlag;
421530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fWidth = gWidth;
431530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fHeight = gHeight;
441530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
45e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info));
461530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    SkCanvas* canvas = surface->getCanvas();
471530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
48c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
49c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
50c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap src;
51deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    src.allocN32Pixels(size.width(), size.height());
52c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    src.eraseColor(SK_ColorBLACK);
53f0ffb8943b7be477b769db23660a80013f3332ebMike Reed    size_t srcSize = src.computeByteSize();
54c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
5595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    size_t initialCacheSize;
5696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    context->getResourceCacheUsage(nullptr, &initialCacheSize);
57c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
58c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    int oldMaxNum;
59c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t oldMaxBytes;
6095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
6117f1ae63d57a3f3d3a0ae50e1b25b3f8b18fd328skia.committer@gmail.com
62c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // Set the cache limits so we can fit 10 "src" images and the
63c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // max number of textures doesn't matter
64c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t maxCacheSize = initialCacheSize + 10*srcSize;
6595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(1000, maxCacheSize);
66c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
67c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap readback;
68deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    readback.allocN32Pixels(size.width(), size.height());
69c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
70c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    for (int i = 0; i < 100; ++i) {
71c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        canvas->drawBitmap(src, 0, 0);
72f19421961c59ceabfb88a5c5cdf7c7e31a95b015Mike Reed        surface->readPixels(readback, 0, 0);
73c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
74c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // "modify" the src texture
75c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        src.notifyPixelsChanged();
76c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
7795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        size_t curCacheSize;
7896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        context->getResourceCacheUsage(nullptr, &curCacheSize);
79c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
80c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // we should never go over the size limit
81c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
82c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    }
83c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
8495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
85c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
86c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
8711abd8d6cb2887bf66711863fb2dfe47da86d979bsalomonstatic bool is_rendering_and_not_angle_es3(sk_gpu_test::GrContextFactory::ContextType type) {
8811abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon    if (type == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES3_ContextType ||
8911abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon        type == sk_gpu_test::GrContextFactory::kANGLE_GL_ES3_ContextType) {
9011abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon        return false;
9111abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon    }
9211abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon    return sk_gpu_test::GrContextFactory::IsRenderingContext(type);
9311abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon}
9411abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon
95c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillipsstatic GrStencilAttachment* get_SB(GrRenderTarget* rt) {
96c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    return rt->renderTargetPriv().getStencilAttachment();
97c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips}
98c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
99c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillipsstatic sk_sp<GrRenderTarget> create_RT_with_SB(GrResourceProvider* provider,
100c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                               int size, int sampleCount, SkBudgeted budgeted) {
101c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    GrSurfaceDesc desc;
102c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fFlags = kRenderTarget_GrSurfaceFlag;
103c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
104c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fWidth = size;
105c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fHeight = size;
106c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
107c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    desc.fSampleCnt = sampleCount;
108c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
109c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    sk_sp<GrTexture> tex(provider->createTexture(desc, budgeted));
110c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    if (!tex || !tex->asRenderTarget()) {
111c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        return nullptr;
112c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    }
113c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
114c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    if (!provider->attachStencilAttachment(tex->asRenderTarget())) {
115c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        return nullptr;
116c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    }
117c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    SkASSERT(get_SB(tex->asRenderTarget()));
118c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
119c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    return sk_ref_sp(tex->asRenderTarget());
120c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips}
121c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
12211abd8d6cb2887bf66711863fb2dfe47da86d979bsalomon// This currently fails on ES3 ANGLE contexts
12311abd8d6cb2887bf66711863fb2dfe47da86d979bsalomonDEF_GPUTEST_FOR_CONTEXTS(ResourceCacheStencilBuffers, &is_rendering_and_not_angle_es3, reporter,
124ec3253472947b0df618261479336a7b50b24f0c8Robert Phillips                         ctxInfo, nullptr) {
1258b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    GrContext* context = ctxInfo.grContext();
1265c77975e4c00e18e644c72b56f369858acd11b15Eric Karl    if (context->caps()->avoidStencilBuffers()) {
1275c77975e4c00e18e644c72b56f369858acd11b15Eric Karl        return;
1285c77975e4c00e18e644c72b56f369858acd11b15Eric Karl    }
1296bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
1306be756b673b823881e90a2ef68c12b640ddde549Robert Phillips    GrResourceProvider* resourceProvider = context->contextPriv().resourceProvider();
131c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
132bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon    sk_sp<GrRenderTarget> smallRT0 = create_RT_with_SB(resourceProvider, 4, 1, SkBudgeted::kYes);
133c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    REPORTER_ASSERT(reporter, smallRT0);
134c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
135c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    {
136c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips       // Two budgeted RTs with the same desc should share a stencil buffer.
137bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon       sk_sp<GrRenderTarget> smallRT1 = create_RT_with_SB(resourceProvider, 4, 1, SkBudgeted::kYes);
138bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon       REPORTER_ASSERT(reporter, smallRT1);
139c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
140bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon       REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) == get_SB(smallRT1.get()));
1416bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
1426bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
143c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    {
144c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        // An unbudgeted RT with the same desc should also share.
145bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        sk_sp<GrRenderTarget> smallRT2 = create_RT_with_SB(resourceProvider, 4, 1, SkBudgeted::kNo);
146c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, smallRT2);
14702a44a488605112aa6683c9d919e13b188112ce1bsalomon
148c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) == get_SB(smallRT2.get()));
1496bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
150c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
151c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips    {
152c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        // An RT with a much larger size should not share.
153bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        sk_sp<GrRenderTarget> bigRT = create_RT_with_SB(resourceProvider, 400, 1, SkBudgeted::kNo);
154c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, bigRT);
155c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
156c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) != get_SB(bigRT.get()));
1576bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
158c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
159bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon    int smallSampleCount = context->caps()->getRenderTargetSampleCount(2, kRGBA_8888_GrPixelConfig);
160bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon    if (smallSampleCount > 1) {
1615f939ab658a228dce34a3b14a545638407150b92mtklein        // An RT with a different sample count should not share.
1626be756b673b823881e90a2ef68c12b640ddde549Robert Phillips        sk_sp<GrRenderTarget> smallMSAART0 = create_RT_with_SB(resourceProvider, 4,
1636be756b673b823881e90a2ef68c12b640ddde549Robert Phillips                                                               smallSampleCount, SkBudgeted::kNo);
164b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#ifdef SK_BUILD_FOR_ANDROID
165b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        if (!smallMSAART0) {
166b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            // The nexus player seems to fail to create MSAA textures.
167b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            return;
168b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        }
169c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips#else
170c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, smallMSAART0);
171b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#endif
172c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
173c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        REPORTER_ASSERT(reporter, get_SB(smallRT0.get()) != get_SB(smallMSAART0.get()));
174c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
175c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips        {
176c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            // A second MSAA RT should share with the first MSAA RT.
1776be756b673b823881e90a2ef68c12b640ddde549Robert Phillips            sk_sp<GrRenderTarget> smallMSAART1 = create_RT_with_SB(resourceProvider, 4,
1786be756b673b823881e90a2ef68c12b640ddde549Robert Phillips                                                                   smallSampleCount,
179c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                                                   SkBudgeted::kNo);
180c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, smallMSAART1);
181c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
182c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, get_SB(smallMSAART0.get()) == get_SB(smallMSAART1.get()));
1836bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        }
184c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
185bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        // But one with a larger sample count should not. (Also check that the two requests didn't
186bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        // rounded up to the same actual sample count or else they could share.).
187bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        int bigSampleCount =
188bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon                context->caps()->getRenderTargetSampleCount(5, kRGBA_8888_GrPixelConfig);
189bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        if (bigSampleCount > 0 && bigSampleCount != smallSampleCount) {
1906be756b673b823881e90a2ef68c12b640ddde549Robert Phillips            sk_sp<GrRenderTarget> smallMSAART2 = create_RT_with_SB(resourceProvider, 4,
1916be756b673b823881e90a2ef68c12b640ddde549Robert Phillips                                                                   bigSampleCount,
192c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips                                                                   SkBudgeted::kNo);
193c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, smallMSAART2);
194c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips
195c0192e346ccdcacedb4d4f1f53a85caa29b97a6fRobert Phillips            REPORTER_ASSERT(reporter, get_SB(smallMSAART0.get()) != get_SB(smallMSAART2.get()));
19602a44a488605112aa6683c9d919e13b188112ce1bsalomon        }
19702a44a488605112aa6683c9d919e13b188112ce1bsalomon    }
19802a44a488605112aa6683c9d919e13b188112ce1bsalomon}
19902a44a488605112aa6683c9d919e13b188112ce1bsalomon
20068d9134bec16e91c4a6cde071bcaa579bc0801a7bsalomonDEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceCacheWrappedResources, reporter, ctxInfo) {
2018b7451aaf6b1c71e9d343a4df107893db277b6aabsalomon    GrContext* context = ctxInfo.grContext();
2026be756b673b823881e90a2ef68c12b640ddde549Robert Phillips    GrResourceProvider* resourceProvider = context->contextPriv().resourceProvider();
203f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
204eeb8d99b4e58eb95cad3f7cd5438b9c2b3db7141jvanverth    // this test is only valid for GL
205eeb8d99b4e58eb95cad3f7cd5438b9c2b3db7141jvanverth    if (!gpu || !gpu->glContextForTesting()) {
2066dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
2076dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
2086dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
209d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    GrBackendTexture backendTextures[2];
2106dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kW = 100;
2116dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kH = 100;
212672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
213d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    backendTextures[0] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH,
214d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              kRGBA_8888_GrPixelConfig,
215d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              false, GrMipMapped::kNo);
216d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    backendTextures[1] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH,
217d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              kRGBA_8888_GrPixelConfig,
218d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips                                                              false, GrMipMapped::kNo);
2195366e59e8826a235d25f34f50ae1b93ee9675663Greg Daniel    REPORTER_ASSERT(reporter, backendTextures[0].isValid());
2205366e59e8826a235d25f34f50ae1b93ee9675663Greg Daniel    REPORTER_ASSERT(reporter, backendTextures[1].isValid());
2215366e59e8826a235d25f34f50ae1b93ee9675663Greg Daniel    if (!backendTextures[0].isValid() || !backendTextures[1].isValid()) {
2225366e59e8826a235d25f34f50ae1b93ee9675663Greg Daniel        return;
2235366e59e8826a235d25f34f50ae1b93ee9675663Greg Daniel    }
224672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
2256dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2266dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2276be756b673b823881e90a2ef68c12b640ddde549Robert Phillips    sk_sp<GrTexture> borrowed(resourceProvider->wrapBackendTexture(
228d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips            backendTextures[0], kBorrow_GrWrapOwnership));
229d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips
2306be756b673b823881e90a2ef68c12b640ddde549Robert Phillips    sk_sp<GrTexture> adopted(resourceProvider->wrapBackendTexture(
231d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips            backendTextures[1], kAdopt_GrWrapOwnership));
2327ef28f35a2f7d17b90c776f76d4b374ccee6c347Greg Daniel
23385d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    REPORTER_ASSERT(reporter, borrowed != nullptr && adopted != nullptr);
23485d34b2e841d99dab914111fe2eaa4db99345e1eBrian Osman    if (!borrowed || !adopted) {
2356dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
2366dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
2376dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
23896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    borrowed.reset(nullptr);
23996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    adopted.reset(nullptr);
2406dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2416dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->flush();
2426dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
243d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(backendTextures[0]);
244d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(backendTextures[1]);
2456dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2466dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, borrowedIsAlive);
2476dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, !adoptedIsAlive);
2486dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
249d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    gpu->deleteTestingOnlyBackendTexture(&(backendTextures[0]), !borrowedIsAlive);
250d21b2a5d5c5dca87b7df02713782e722a2c0ae92Robert Phillips    gpu->deleteTestingOnlyBackendTexture(&(backendTextures[1]), !adoptedIsAlive);
2516dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2526dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2536dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon}
2546dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2556d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomonclass TestResource : public GrGpuResource {
2561c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    enum ScratchConstructor { kScratchConstructor };
257c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgpublic:
2586e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    static const size_t kDefaultSize = 100;
2595f939ab658a228dce34a3b14a545638407150b92mtklein
2601c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    /** Property that distinctly categorizes the resource.
2611c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon     * For example, textures have width, height, ... */
26223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
2631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2642e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, SkBudgeted budgeted = SkBudgeted::kYes, size_t size = kDefaultSize)
2652e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
26696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
2671c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(size)
2682e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(kA_SimulatedProperty)
2692e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(false) {
2705236cf480daf82b2f36e42795abdbbc915533a59bsalomon        ++fNumAlive;
2712e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCache(budgeted);
2725236cf480daf82b2f36e42795abdbbc915533a59bsalomon    }
2735236cf480daf82b2f36e42795abdbbc915533a59bsalomon
2742e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    static TestResource* CreateScratch(GrGpu* gpu, SkBudgeted budgeted,
2752e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                       SimulatedProperty property) {
2762e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        return new TestResource(gpu, budgeted, property, kScratchConstructor);
2778b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
2782e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    static TestResource* CreateWrapped(GrGpu* gpu, size_t size = kDefaultSize) {
2792e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        return new TestResource(gpu, size);
280c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
281c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
282d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~TestResource() override {
283334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon        --fNumAlive;
28471cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkSafeUnref(fToDelete);
285c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
286c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
28711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void setSize(size_t size) {
28811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        fSize = size;
28911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        this->didChangeGpuMemorySize();
29011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
29111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
292334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int NumAlive() { return fNumAlive; }
293c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
29471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setUnrefWhenDestroyed(TestResource* resource) {
29571cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkRefCnt_SafeAssign(fToDelete, resource);
296c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
297c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
2981c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
2991c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
3001c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
30124db3b1c35fb935660229da164fc5ad31977387fbsalomon        for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
30224db3b1c35fb935660229da164fc5ad31977387fbsalomon            builder[i] = static_cast<uint32_t>(i + property);
3031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        }
3041c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
3051c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
3061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static size_t ExpectedScratchKeySize() {
3071c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
3081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
309c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgprivate:
31024db3b1c35fb935660229da164fc5ad31977387fbsalomon    static const int kScratchKeyFieldCnt = 6;
3111c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
3122e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, SkBudgeted budgeted, SimulatedProperty property, ScratchConstructor)
3132e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
31496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
3151c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
3162e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(property)
3172e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(true) {
3181c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ++fNumAlive;
3192e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCache(budgeted);
3202e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    }
3212e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
3222e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    // Constructor for simulating resources that wrap backend objects.
3232e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    TestResource(GrGpu* gpu, size_t size)
3242e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        : INHERITED(gpu)
3252e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fToDelete(nullptr)
3262e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fSize(size)
3272e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fProperty(kA_SimulatedProperty)
3282e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        , fIsScratch(false) {
3292e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        ++fNumAlive;
3302e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        this->registerWithCacheWrapped();
3312e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    }
3322e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
3332e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    void computeScratchKey(GrScratchKey* key) const override {
3342e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        if (fIsScratch) {
3352e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen            ComputeScratchKey(fProperty, key);
3362e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen        }
3371c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
3381c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
33936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t onGpuMemorySize() const override { return fSize; }
34067914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger    const char* getResourceType() const override { return "Test"; }
34169ed47f42d4877c178fdc0031cb01af2966ae235bsalomon
342c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    TestResource* fToDelete;
34311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    size_t fSize;
344334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int fNumAlive;
3451c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    SimulatedProperty fProperty;
3462e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen    bool fIsScratch;
3476d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    typedef GrGpuResource INHERITED;
348c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org};
349334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonint TestResource::fNumAlive = 0;
350c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
351c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonclass Mock {
352c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonpublic:
353c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock(int maxCnt, size_t maxBytes) {
35402611d9afdd887ee443825ac88377f2eea093380Greg Daniel        fContext = GrContext::MakeMock(nullptr);
355c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        SkASSERT(fContext);
356c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext->setResourceCacheLimits(maxCnt, maxBytes);
3576be756b673b823881e90a2ef68c12b640ddde549Robert Phillips        GrResourceCache* cache = fContext->contextPriv().getResourceCache();
3580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        cache->purgeAllUnlocked();
3590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
36071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
361c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
3626be756b673b823881e90a2ef68c12b640ddde549Robert Phillips    GrResourceCache* cache() { return fContext->contextPriv().getResourceCache(); }
363c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
364342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    GrContext* context() { return fContext.get(); }
365c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
366c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonprivate:
367342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrContext> fContext;
368c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon};
369c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
370c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_no_key(skiatest::Reporter* reporter) {
371c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
372c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
3730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
374f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
37571cb0c241e439b6ed746b90294d0b6916644a644bsalomon
37671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Create a bunch of resources with no keys
377f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = new TestResource(gpu);
378f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = new TestResource(gpu);
379f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* c = new TestResource(gpu);
380f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* d = new TestResource(gpu);
38171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->setSize(11);
38271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->setSize(12);
38371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->setSize(13);
38471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->setSize(14);
38571cb0c241e439b6ed746b90294d0b6916644a644bsalomon
38671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
3870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
38871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
3890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              d->gpuMemorySize() == cache->getResourceBytes());
39071cb0c241e439b6ed746b90294d0b6916644a644bsalomon
39171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Should be safe to purge without deleting the resources since we still have refs.
3920ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
39371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
39471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3958718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Since the resources have neither unique nor scratch keys, delete immediately upon unref.
39671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
39771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->unref();
39871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
3990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
40071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
4010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
40271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
40371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->unref();
40471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
4050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
40671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
4070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
40871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
40971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->unref();
41071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
4110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
41371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
41471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->unref();
41571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
4160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
4170ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
41871cb0c241e439b6ed746b90294d0b6916644a644bsalomon}
41971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
42024db3b1c35fb935660229da164fc5ad31977387fbsalomon// Each integer passed as a template param creates a new domain.
4211090da6433db575d59b93aec99f6bda49b808b84Brian Salomontemplate <int>
4221090da6433db575d59b93aec99f6bda49b808b84Brian Salomonstatic void make_unique_key(GrUniqueKey* key, int data, const char* tag = nullptr) {
4238718aafec239c93485e45bbe8fed19d9a8def079bsalomon    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
4241090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrUniqueKey::Builder builder(key, d, 1, tag);
42524db3b1c35fb935660229da164fc5ad31977387fbsalomon    builder[0] = data;
42624db3b1c35fb935660229da164fc5ad31977387fbsalomon}
42724db3b1c35fb935660229da164fc5ad31977387fbsalomon
42847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillipsstatic void test_purge_unlocked(skiatest::Reporter* reporter) {
42947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    Mock mock(10, 30000);
43047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    GrContext* context = mock.context();
43147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    GrResourceCache* cache = mock.cache();
43247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
43347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
43447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    // Create two resource w/ a unique key and two w/o but all of which have scratch keys.
43547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    TestResource* a = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
43647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                                                  TestResource::kA_SimulatedProperty);
43747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    a->setSize(11);
43847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
43947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    GrUniqueKey uniqueKey;
44047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    make_unique_key<0>(&uniqueKey, 0);
44147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
44247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    TestResource* b = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
44347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                                                  TestResource::kA_SimulatedProperty);
44447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    b->setSize(12);
44547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    b->resourcePriv().setUniqueKey(uniqueKey);
44647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
44747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    TestResource* c = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
44847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                                                  TestResource::kA_SimulatedProperty);
44947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    c->setSize(13);
45047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
45147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    GrUniqueKey uniqueKey2;
45247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    make_unique_key<0>(&uniqueKey2, 1);
45347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
45447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    TestResource* d = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
45547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                                                  TestResource::kA_SimulatedProperty);
45647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    d->setSize(14);
45747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    d->resourcePriv().setUniqueKey(uniqueKey2);
45847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
45947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
46047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
46147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
46247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
46347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                              d->gpuMemorySize() == cache->getResourceBytes());
46447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
46547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    // Should be safe to purge without deleting the resources since we still have refs.
46647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    cache->purgeUnlockedResources(false);
46747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
46847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
46947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    // Unref them all. Since they all have keys they should remain in the cache.
47047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
47147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    a->unref();
47247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    b->unref();
47347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    c->unref();
47447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    d->unref();
47547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
47647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
47747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
47847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                              d->gpuMemorySize() == cache->getResourceBytes());
47947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
48047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    // Purge only the two scratch resources
48147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    cache->purgeUnlockedResources(true);
48247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
48347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
48447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
48547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
48647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips                              cache->getResourceBytes());
48747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
48847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    // Purge the uniquely keyed resources
48947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    cache->purgeUnlockedResources(false);
49047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
49147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
49247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
49347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
49447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips}
49547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips
49684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomonstatic void test_budgeting(skiatest::Reporter* reporter) {
497c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
498c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
4990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
500f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
501dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
5028718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
5038718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
504dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
5058718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create a scratch, a unique, and a wrapped resource
5061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    TestResource* scratch =
507f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips            TestResource::CreateScratch(gpu, SkBudgeted::kYes, TestResource::kB_SimulatedProperty);
508dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(10);
509f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* unique = new TestResource(gpu);
5108718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
511f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
512f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* wrapped = TestResource::CreateWrapped(gpu);
5135236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->setSize(12);
514f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* unbudgeted = new TestResource(gpu, SkBudgeted::kNo);
51584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->setSize(13);
516dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
5170562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    // Make sure we can add a unique key to the wrapped resource
5188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey2;
5198718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey2, 1);
520f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    wrapped->resourcePriv().setUniqueKey(uniqueKey2);
5210562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    GrGpuResource* wrappedViaKey = cache->findAndRefUniqueResource(uniqueKey2);
5220562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    REPORTER_ASSERT(reporter, wrappedViaKey != nullptr);
5230562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman
5240562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    // Remove the extra ref we just added.
5250562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman    wrappedViaKey->unref();
526dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
527dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Make sure sizes are as we expect
5280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
5298718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
53084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
5310ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
5320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5338718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
5340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
535ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
536dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
53763c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
5380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
5408718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
54184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
5420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
5430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5448718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
5450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
546ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
547dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
548dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Unreffing the wrapped resource should free it right away.
549dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
5500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5518718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
5520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
553ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
554dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
55584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    // Now try freeing the budgeted resources first
556f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    wrapped = TestResource::CreateWrapped(gpu);
557dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(12);
5588718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
559ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 11 == cache->getPurgeableBytes());
5600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5610ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
56284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
5630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
5640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes());
566ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
567dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
568dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->unref();
569ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 12 == cache->getPurgeableBytes());
5700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
57284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
5730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
5740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
576ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
577dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
578dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
5790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes());
5810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
583ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
58484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
58584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->unref();
5860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5880ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
590ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
591dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon}
592dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
5935236cf480daf82b2f36e42795abdbbc915533a59bsalomonstatic void test_unbudgeted(skiatest::Reporter* reporter) {
594c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
595c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
597f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
5985236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5998718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
6008718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
6015236cf480daf82b2f36e42795abdbbc915533a59bsalomon
6025236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* scratch;
6038718aafec239c93485e45bbe8fed19d9a8def079bsalomon    TestResource* unique;
6045236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* wrapped;
6055236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* unbudgeted;
6065236cf480daf82b2f36e42795abdbbc915533a59bsalomon
6075236cf480daf82b2f36e42795abdbbc915533a59bsalomon    // A large uncached or wrapped resource shouldn't evict anything.
608f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    scratch = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
6092e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                          TestResource::kB_SimulatedProperty);
6102e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen
6115236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->setSize(10);
6125236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->unref();
6130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes());
6150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
6160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes());
617ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 10 == cache->getPurgeableBytes());
6185236cf480daf82b2f36e42795abdbbc915533a59bsalomon
619f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    unique = new TestResource(gpu);
6208718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
621f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
6228718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
6230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
6240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
6250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
6260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
627ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
6285236cf480daf82b2f36e42795abdbbc915533a59bsalomon
6290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    size_t large = 2 * cache->getResourceBytes();
630f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    unbudgeted = new TestResource(gpu, SkBudgeted::kNo, large);
6310ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
6320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
6330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
6340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
635ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
6365236cf480daf82b2f36e42795abdbbc915533a59bsalomon
6375236cf480daf82b2f36e42795abdbbc915533a59bsalomon    unbudgeted->unref();
6380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
6390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
6400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
6410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
642ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
6435236cf480daf82b2f36e42795abdbbc915533a59bsalomon
644f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    wrapped = TestResource::CreateWrapped(gpu, large);
6450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
6460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
6470ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
6480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
649ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
6505236cf480daf82b2f36e42795abdbbc915533a59bsalomon
6515236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->unref();
6520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
6530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
6540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
6550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
656ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes());
6570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon
6580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
6600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
6610ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
6620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
663ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
6645236cf480daf82b2f36e42795abdbbc915533a59bsalomon}
6655236cf480daf82b2f36e42795abdbbc915533a59bsalomon
6663582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon// This method can't be static because it needs to friended in GrGpuResource::CacheAccess.
6673582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomonvoid test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
6683582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon/*static*/ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
669c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
670c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
6710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
672f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
673c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
674c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* resource =
675f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource::CreateScratch(gpu, SkBudgeted::kNo, TestResource::kA_SimulatedProperty);
676c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrScratchKey key;
67723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
678c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
679c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    size_t size = resource->gpuMemorySize();
680c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    for (int i = 0; i < 2; ++i) {
681c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Since this resource is unbudgeted, it should not be reachable as scratch.
6823582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
683c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
6845ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        REPORTER_ASSERT(reporter, SkBudgeted::kNo == resource->resourcePriv().isBudgeted());
68596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
6860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6880ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
6890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
690ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
691c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
692c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Once it is unrefed, it should become available as scratch.
693c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        resource->unref();
6940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
6950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
6960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
6970ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
698ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger        REPORTER_ASSERT(reporter, size == cache->getPurgeableBytes());
6996e83ac778f8f90939abe3aee3ea865428dff592frobertphillips        resource = static_cast<TestResource*>(cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
700c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource);
7013582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
702c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
7035ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
704c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
705c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        if (0 == i) {
7065f939ab658a228dce34a3b14a545638407150b92mtklein            // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
707c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // the above tests again.
7083582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().makeUnbudgeted();
709c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        } else {
710c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // After the second time around, try removing the scratch key
7113582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().removeScratchKey();
7120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
7130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
7140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
7150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
716ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger            REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
7173582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid());
718c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
7195ec26ae9bfca635ccc98283aad5deda11519d826bsalomon            REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
720c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
721c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // now when it is unrefed it should die since it has no key.
722c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            resource->unref();
7230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
7240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
7250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
7260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
727ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger            REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
728c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        }
7298b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
730c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon}
731c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
732c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
733c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
734c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
736f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
7378b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
7388b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Create two resources that have the same scratch key.
739f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = TestResource::CreateScratch(gpu,
7402e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                  SkBudgeted::kYes,
74123e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
742f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = TestResource::CreateScratch(gpu,
7432e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen                                                  SkBudgeted::kYes,
74423e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7458b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
7468b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->setSize(12);
7471c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
74823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
7491c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Check for negative case consistency. (leaks upon test failure.)
75096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(scratchKey1, TestResource::kDefaultSize, 0));
7511c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7521c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
75323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
7541c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
756ac49acda520292b059bc37fd368dff912626c3d9bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
7580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
75971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
7600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
7618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
76263c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
7630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
7648b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
7668b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
7678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Unref but don't purge
7688b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->unref();
7698b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
7708b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
7728b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
77363c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Purge again. This time resources should be purgeable.
7740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
7758b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
7760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
7770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7788b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
7798b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
78010e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_remove_scratch_key(skiatest::Reporter* reporter) {
781c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
782c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
784f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
78510e23caea3106be125acea10a637789e5a15c728bsalomon
78610e23caea3106be125acea10a637789e5a15c728bsalomon    // Create two resources that have the same scratch key.
787f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
78823e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
789f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
79023e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
79110e23caea3106be125acea10a637789e5a15c728bsalomon    a->unref();
79210e23caea3106be125acea10a637789e5a15c728bsalomon    b->unref();
79310e23caea3106be125acea10a637789e5a15c728bsalomon
7941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
7951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
79623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
7971c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
79896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
7991c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
80123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
80210e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8030ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
8040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
80510e23caea3106be125acea10a637789e5a15c728bsalomon
80610e23caea3106be125acea10a637789e5a15c728bsalomon    // Find the first resource and remove its scratch key
80710e23caea3106be125acea10a637789e5a15c728bsalomon    GrGpuResource* find;
8086e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
8093582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
81010e23caea3106be125acea10a637789e5a15c728bsalomon    // It's still alive, but not cached by scratch key anymore
81110e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
8130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
81410e23caea3106be125acea10a637789e5a15c728bsalomon
81510e23caea3106be125acea10a637789e5a15c728bsalomon    // The cache should immediately delete it when it's unrefed since it isn't accessible.
81610e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
81710e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
8180ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
8190ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
82010e23caea3106be125acea10a637789e5a15c728bsalomon
82110e23caea3106be125acea10a637789e5a15c728bsalomon    // Repeat for the second resource.
8226e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
8233582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
82410e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
8250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
8260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
82710e23caea3106be125acea10a637789e5a15c728bsalomon
82810e23caea3106be125acea10a637789e5a15c728bsalomon    // Should be able to call this multiple times with no problem.
8293582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
83010e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
8310ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
8320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
83310e23caea3106be125acea10a637789e5a15c728bsalomon
83410e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
83510e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
8360ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
8370ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
83810e23caea3106be125acea10a637789e5a15c728bsalomon}
83910e23caea3106be125acea10a637789e5a15c728bsalomon
8401c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomonstatic void test_scratch_key_consistency(skiatest::Reporter* reporter) {
841c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
842c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
8430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
844f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
8451c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8461c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Create two resources that have the same scratch key.
847f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
84823e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
849f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
85023e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
8511c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    a->unref();
8521c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    b->unref();
8531c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8541c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
8551c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key comparison and assignment is consistent.
8561c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
85723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
8581c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey2;
85923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
8601c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
8611c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
8621c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
8631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey1;
8641c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
8651c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 == scratchKey);
8661c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey1);
8671c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey);
8681c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey2);
8691c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey2;
8701c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
8711c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
8721c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
8731c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
8741c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
8751c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8761c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
87723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
8781c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
87996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
8801c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8811c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Find the first resource with a scratch key and a copy of a scratch key.
88223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
8836e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
88496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
8851c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
8861c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8871c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey2 = scratchKey;
8886e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
88996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
8901c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find == a || find == b);
8911c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
8926e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find2 = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
89396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find2 != nullptr);
8941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 == a || find2 == b);
8951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 != find);
8961c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find2->unref();
8971c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
8981c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon}
8991c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
9008718aafec239c93485e45bbe8fed19d9a8def079bsalomonstatic void test_duplicate_unique_key(skiatest::Reporter* reporter) {
901c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
902c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9030ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
904f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
9058b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9068718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key;
9078718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key, 0);
9085f939ab658a228dce34a3b14a545638407150b92mtklein
9098718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create two resources that we will attempt to register with the same unique key.
910f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = new TestResource(gpu);
9118b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
9125f939ab658a228dce34a3b14a545638407150b92mtklein
913f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Set key on resource a.
914f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
915f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
916f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
917f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
918f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Make sure that redundantly setting a's key works.
919f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
920f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
921f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
922f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
923f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache->getResourceBytes());
924f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
925f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
926f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Create resource b and set the same key. It should replace a's unique key cache entry.
927f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = new TestResource(gpu);
928f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->setSize(12);
929f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->resourcePriv().setUniqueKey(key);
930f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b == cache->findAndRefUniqueResource(key));
931f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->unref();
93271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
933f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Still have two resources because a is still reffed.
9340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
935f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
9368b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9378b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
938f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
939f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now a should be gone.
940f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
941f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
942f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
943f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
944f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now replace b with c, but make sure c can start with one unique key and change it to b's key.
945f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Also make b be unreffed when replacement occurs.
9468b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
947f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* c = new TestResource(gpu);
948f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    GrUniqueKey differentKey;
949f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    make_unique_key<0>(&differentKey, 1);
950f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->setSize(13);
951f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(differentKey);
952f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
953f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() == cache->getResourceBytes());
954f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
955f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c replaces b and b should be immediately purged.
956f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(key);
9570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
958f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
95971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
96071cb0c241e439b6ed746b90294d0b6916644a644bsalomon
961f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c shouldn't be purged because it is ref'ed.
9620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
9630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
964f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
9658b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
9668b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
967f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Drop the ref on c, it should be kept alive because it has a unique key.
968f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
9690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
970f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
97171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
97271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
973f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Verify that we can find c, then remove its unique key. It should get purged immediately.
974f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c == cache->findAndRefUniqueResource(key));
975f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().removeUniqueKey();
976f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
9770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
9780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
9798b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
98084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
98184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    {
98284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        GrUniqueKey key2;
98384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        make_unique_key<0>(&key2, 0);
984f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        sk_sp<TestResource> d(new TestResource(gpu));
98584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        int foo = 4132;
98638d909ec2875f79952de08f36adfaac5680d2c53bungeman        key2.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
98784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        d->resourcePriv().setUniqueKey(key2);
98884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    }
98984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
99084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3;
99184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key3, 0);
992342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary    sk_sp<GrGpuResource> d2(cache->findAndRefUniqueResource(key3));
99384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) d2->getUniqueKey().getCustomData()->data() == 4132);
9948b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
9958b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9968b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_purge_invalidated(skiatest::Reporter* reporter) {
997c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
998c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
1000f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
10018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
10028718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2, key3;
10038718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
10048718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
10058718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key3, 3);
10065f939ab658a228dce34a3b14a545638407150b92mtklein
100723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Add three resources to the cache. Only c is usable as scratch.
1008f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = new TestResource(gpu);
1009f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = new TestResource(gpu);
1010f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* c = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
101123e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kA_SimulatedProperty);
10128718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
10138718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
10148718aafec239c93485e45bbe8fed19d9a8def079bsalomon    c->resourcePriv().setUniqueKey(key3);
1015c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    a->unref();
101623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // hold b until *after* the message is sent.
10178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    c->unref();
1018c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
10198718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
10208718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
10218718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
1022334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
102323e619cf462b2a8a500f3ca750e099f79601f508bsalomon
10248718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef GrUniqueKeyInvalidatedMessage Msg;
10258718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkMessageBus<GrUniqueKeyInvalidatedMessage> Bus;
102623e619cf462b2a8a500f3ca750e099f79601f508bsalomon
102723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Invalidate two of the three, they should be purged and no longer accessible via their keys.
102823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key1));
102923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key2));
10300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
103123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // a should be deleted now, but we still have a ref on b.
10328718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
10338718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
103423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
10358718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
10368b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
10378b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Invalidate the third.
103823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key3));
10390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
104023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // we still have a ref on b, c should be recycled as scratch.
104123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
10428718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key3));
104371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
104423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // make b purgeable. It should be immediately deleted since it has no key.
104523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    b->unref();
104623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
104723e619cf462b2a8a500f3ca750e099f79601f508bsalomon
104823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Make sure we actually get to c via it's scratch key, before we say goodbye.
104923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    GrScratchKey scratchKey;
105023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
10516e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
105223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, scratch == c);
105323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
105423e619cf462b2a8a500f3ca750e099f79601f508bsalomon
105523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Get rid of c.
10560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
10576e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
105871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
10590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
10600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
106123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, !scratch);
106223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
1063c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org}
1064c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
106571cb0c241e439b6ed746b90294d0b6916644a644bsalomonstatic void test_cache_chained_purge(skiatest::Reporter* reporter) {
1066c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(3, 30000);
1067c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
10680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
1069f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
10708b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
10718718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
10728718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
10738718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
1074bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
1075f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* a = new TestResource(gpu);
1076f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    TestResource* b = new TestResource(gpu);
10778718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
10788718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
107971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
1080c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Make a cycle
1081c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->setUnrefWhenDestroyed(b);
1082c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->setUnrefWhenDestroyed(a);
1083334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
1084c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1085334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
1086c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->unref();
1087c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->unref();
10888b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
1089c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
10908b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
10910ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
1092c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1093f21dab95405979a4aff9f6a741c818304a67f220bsalomon
1094c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Break the cycle
109596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    a->setUnrefWhenDestroyed(nullptr);
1096c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
1097ac49acda520292b059bc37fd368dff912626c3d9bsalomon
10980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
1099c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
1100bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org}
1101bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
11028b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_resource_size_changed(skiatest::Reporter* reporter) {
11038718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
11048718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
11058718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
110611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
110711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test changing resources sizes (both increase & decrease).
110811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1109c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(3, 30000);
1110c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
11110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
1112f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        GrGpu* gpu = context->contextPriv().getGpu();
111311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1114f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource* a = new TestResource(gpu);
11158718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
111611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
111711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1118f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource* b = new TestResource(gpu);
11198718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
112011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
112111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
11220ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
11230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
11248b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
1125342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find2(
11268718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key2)));
11278b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(200);
1128342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find1(
11298718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key1)));
11308b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find1->setSize(50);
11318b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
113211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
11330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 250 == cache->getResourceBytes());
11340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
113511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
113611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
113711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test increasing a resources size beyond the cache budget.
113811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1139c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(2, 300);
1140c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
11410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
1142f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        GrGpu* gpu = context->contextPriv().getGpu();
114311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1144f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource* a = new TestResource(gpu);
11458b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        a->setSize(100);
11468718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
114711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
114811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1149f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource* b = new TestResource(gpu);
11508b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        b->setSize(100);
11518718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
115211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
115311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
11540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
11550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
115611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
11578b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
1158342b7acc46550af5fbefc6f9313231ede11ed692Hal Canary            sk_sp<TestResource> find2(static_cast<TestResource*>(
11598718aafec239c93485e45bbe8fed19d9a8def079bsalomon                cache->findAndRefUniqueResource(key2)));
11608b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(201);
11618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
11628718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
116311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
11640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 201 == cache->getResourceBytes());
11650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
116611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
116711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org}
116811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1169ddf30e64fe474847b204d7062fad3341d245062cbsalomonstatic void test_timestamp_wrap(skiatest::Reporter* reporter) {
1170ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kCount = 50;
1171ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetCnt = kCount / 2;
1172ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kLockedFreq = 8;
1173ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetSize = 0x80000000;
1174ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1175ddf30e64fe474847b204d7062fad3341d245062cbsalomon    SkRandom random;
1176ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1177ddf30e64fe474847b204d7062fad3341d245062cbsalomon    // Run the test 2*kCount times;
1178ddf30e64fe474847b204d7062fad3341d245062cbsalomon    for (int i = 0; i < 2 * kCount; ++i ) {
1179ddf30e64fe474847b204d7062fad3341d245062cbsalomon        Mock mock(kBudgetCnt, kBudgetSize);
1180ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrContext* context = mock.context();
1181ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrResourceCache* cache = mock.cache();
1182f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        GrGpu* gpu = context->contextPriv().getGpu();
1183ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1184ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Pick a random number of resources to add before the timestamp will wrap.
1185ddf30e64fe474847b204d7062fad3341d245062cbsalomon        cache->changeTimestamp(SK_MaxU32 - random.nextULessThan(kCount + 1));
1186ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1187ddf30e64fe474847b204d7062fad3341d245062cbsalomon        static const int kNumToPurge = kCount - kBudgetCnt;
1188ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1189ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<int> shouldPurgeIdxs;
1190ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int purgeableCnt = 0;
1191ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<GrGpuResource*> resourcesToUnref;
1192ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1193ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Add kCount resources, holding onto resources at random so we have a mix of purgeable and
1194ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // unpurgeable resources.
1195ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1196ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1197ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1198ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1199f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips            TestResource* r = new TestResource(gpu);
1200ddf30e64fe474847b204d7062fad3341d245062cbsalomon            r->resourcePriv().setUniqueKey(key);
1201ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (random.nextU() % kLockedFreq) {
1202ddf30e64fe474847b204d7062fad3341d245062cbsalomon                // Make this is purgeable.
1203ddf30e64fe474847b204d7062fad3341d245062cbsalomon                r->unref();
1204ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++purgeableCnt;
1205ddf30e64fe474847b204d7062fad3341d245062cbsalomon                if (purgeableCnt <= kNumToPurge) {
1206ddf30e64fe474847b204d7062fad3341d245062cbsalomon                    *shouldPurgeIdxs.append() = j;
1207ddf30e64fe474847b204d7062fad3341d245062cbsalomon                }
1208ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
1209ddf30e64fe474847b204d7062fad3341d245062cbsalomon                *resourcesToUnref.append() = r;
1210ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1211ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1212ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1213ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Verify that the correct resources were purged.
1214ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int currShouldPurgeIdx = 0;
1215ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1216ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1217ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1218ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrGpuResource* res = cache->findAndRefUniqueResource(key);
1219ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (currShouldPurgeIdx < shouldPurgeIdxs.count() &&
1220ddf30e64fe474847b204d7062fad3341d245062cbsalomon                shouldPurgeIdxs[currShouldPurgeIdx] == j) {
1221ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++currShouldPurgeIdx;
122296fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr == res);
1223ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
122496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr != res);
1225ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1226ddf30e64fe474847b204d7062fad3341d245062cbsalomon            SkSafeUnref(res);
1227ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1228ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1229ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < resourcesToUnref.count(); ++j) {
1230ddf30e64fe474847b204d7062fad3341d245062cbsalomon            resourcesToUnref[j]->unref();
1231ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1232ddf30e64fe474847b204d7062fad3341d245062cbsalomon    }
1233ddf30e64fe474847b204d7062fad3341d245062cbsalomon}
1234ddf30e64fe474847b204d7062fad3341d245062cbsalomon
12353f324321cdd8fde7976d958e2888a1ec4e657e35bsalomonstatic void test_flush(skiatest::Reporter* reporter) {
12363f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    Mock mock(1000000, 1000000);
12373f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrContext* context = mock.context();
12383f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrResourceCache* cache = mock.cache();
1239f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
12403f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12413f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // The current cache impl will round the max flush count to the next power of 2. So we choose a
12423f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // power of two here to keep things simpler.
12433f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    static const int kFlushCount = 16;
12443f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    cache->setLimits(1000000, 1000000, kFlushCount);
12453f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
12473f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Insert a resource and send a flush notification kFlushCount times.
12483f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1249f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips            TestResource* r = new TestResource(gpu);
12503f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
12513f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
12523f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
12533f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->unref();
1254b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
12553f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12563f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Send flush notifications to the cache. Each flush should purge the oldest resource.
1258e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        for (int i = 0; i < kFlushCount; ++i) {
1259e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
12603f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount - i - 1 == cache->getResourceCount());
12613f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            for (int j = 0; j < i; ++j) {
12623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrUniqueKey k;
12633f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                make_unique_key<1>(&k, j);
12643f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrGpuResource* r = cache->findAndRefUniqueResource(k);
12653f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                REPORTER_ASSERT(reporter, !SkToBool(r));
12663f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                SkSafeUnref(r);
12673f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
12683f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12693f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12703f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
12713f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
12723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
12733f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12743f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // Do a similar test but where we leave refs on some resources to prevent them from being
12753f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // purged.
12763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
12773f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        GrGpuResource* refedResources[kFlushCount >> 1];
12783f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1279f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips            TestResource* r = new TestResource(gpu);
12803f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
12813f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
12823f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
12833f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Leave a ref on every other resource, beginning with the first.
12843f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            if (SkToBool(i & 0x1)) {
12853f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                refedResources[i/2] = r;
12863f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            } else {
12873f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                r->unref();
12883f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
1289b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
12903f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12913f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12923f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
12933f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Should get a resource purged every other flush.
1294b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
1295e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon            REPORTER_ASSERT(reporter, kFlushCount - i/2 - 1 == cache->getResourceCount());
12963f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
12973f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
12983f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Unref all the resources that we kept refs on in the first loop.
12993f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount >> 1; ++i) {
13003f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            refedResources[i]->unref();
13013f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
13023f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
1303e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        // After kFlushCount + 1 flushes they all will have sat in the purgeable queue for
1304e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        // kFlushCount full flushes.
1305e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon        for (int i = 0; i < kFlushCount + 1; ++i) {
13063f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount >> 1 == cache->getResourceCount());
1307b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon            cache->notifyFlushOccurred(GrResourceCache::kExternal);
13083f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
13093f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
13103f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
13113f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
13123f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
13133f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
13143f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
1315dc43898bbbd06202562514ae785116e0cc40f825bsalomon
1316dc43898bbbd06202562514ae785116e0cc40f825bsalomon    // Verify that calling flush() on a GrContext with nothing to do will not trigger resource
1317dc43898bbbd06202562514ae785116e0cc40f825bsalomon    // eviction.
1318dc43898bbbd06202562514ae785116e0cc40f825bsalomon    context->flush();
1319dc43898bbbd06202562514ae785116e0cc40f825bsalomon    for (int i = 0; i < 10; ++i) {
1320f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource* r = new TestResource(gpu);
1321dc43898bbbd06202562514ae785116e0cc40f825bsalomon        GrUniqueKey k;
1322dc43898bbbd06202562514ae785116e0cc40f825bsalomon        make_unique_key<1>(&k, i);
1323dc43898bbbd06202562514ae785116e0cc40f825bsalomon        r->resourcePriv().setUniqueKey(k);
1324dc43898bbbd06202562514ae785116e0cc40f825bsalomon        r->unref();
1325dc43898bbbd06202562514ae785116e0cc40f825bsalomon    }
1326dc43898bbbd06202562514ae785116e0cc40f825bsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
1327dc43898bbbd06202562514ae785116e0cc40f825bsalomon    for (int i = 0; i < 10 * kFlushCount; ++i) {
1328dc43898bbbd06202562514ae785116e0cc40f825bsalomon        context->flush();
1329dc43898bbbd06202562514ae785116e0cc40f825bsalomon    }
1330dc43898bbbd06202562514ae785116e0cc40f825bsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
13313f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon}
13323f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
13335e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomonstatic void test_time_purge(skiatest::Reporter* reporter) {
13345e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    Mock mock(1000000, 1000000);
13355e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    GrContext* context = mock.context();
13365e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    GrResourceCache* cache = mock.cache();
1337f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
13385e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13395e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    static constexpr int kCnts[] = {1, 10, 1024};
13405e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    auto nowish = []() {
13415e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // We sleep so that we ensure we get a value that is greater than the last call to
13425e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // GrStdSteadyClock::now().
13435e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::this_thread::sleep_for(GrStdSteadyClock::duration(5));
13445e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        auto result = GrStdSteadyClock::now();
13455e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Also sleep afterwards so we don't get this value again.
13465e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::this_thread::sleep_for(GrStdSteadyClock::duration(5));
13475e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        return result;
13485e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    };
13495e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13505e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    for (int cnt : kCnts) {
13515e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        std::unique_ptr<GrStdSteadyClock::time_point[]> timeStamps(
13525e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                new GrStdSteadyClock::time_point[cnt]);
13535e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        {
13545e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Insert resources and get time points between each addition.
13555e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
1356f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips                TestResource* r = new TestResource(gpu);
13575e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                GrUniqueKey k;
13585e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                make_unique_key<1>(&k, i);
13595e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->resourcePriv().setUniqueKey(k);
13605e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->unref();
13615e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                timeStamps.get()[i] = nowish();
13625e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13635e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13645e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Purge based on the time points between resource additions. Each purge should remove
13655e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // the oldest resource.
13665e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
13675e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(timeStamps[i]);
13685e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt - i - 1 == cache->getResourceCount());
13695e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                for (int j = 0; j < i; ++j) {
13705e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    GrUniqueKey k;
13715e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    make_unique_key<1>(&k, j);
13725e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    GrGpuResource* r = cache->findAndRefUniqueResource(k);
13735e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    REPORTER_ASSERT(reporter, !SkToBool(r));
13745e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    SkSafeUnref(r);
13755e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                }
13765e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13775e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13785e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
13795e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            cache->purgeAllUnlocked();
13805e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
13815e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
13825e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Do a similar test but where we leave refs on some resources to prevent them from being
13835e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // purged.
13845e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        {
13855e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            std::unique_ptr<GrGpuResource* []> refedResources(new GrGpuResource*[cnt / 2]);
13865e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
1387f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips                TestResource* r = new TestResource(gpu);
13885e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                GrUniqueKey k;
13895e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                make_unique_key<1>(&k, i);
13905e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                r->resourcePriv().setUniqueKey(k);
13915e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                // Leave a ref on every other resource, beginning with the first.
13925e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                if (SkToBool(i & 0x1)) {
13935e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    refedResources.get()[i / 2] = r;
13945e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                } else {
13955e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                    r->unref();
13965e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                }
13975e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                timeStamps.get()[i] = nowish();
13985e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
13995e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
14005e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < cnt; ++i) {
14015e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                // Should get a resource purged every other frame.
14025e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(timeStamps[i]);
14035e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt - i / 2 - 1 == cache->getResourceCount());
14045e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
14055e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
14065e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            // Unref all the resources that we kept refs on in the first loop.
14075e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            for (int i = 0; i < (cnt / 2); ++i) {
14085e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                refedResources.get()[i]->unref();
14095e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                cache->purgeResourcesNotUsedSince(nowish());
14105e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon                REPORTER_ASSERT(reporter, cnt / 2 - i - 1 == cache->getResourceCount());
14115e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            }
14125e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
14135e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            cache->purgeAllUnlocked();
14145e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
14155e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
14165e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
14175e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
14185e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // Verify that calling flush() on a GrContext with nothing to do will not trigger resource
14195e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        // eviction
14205e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        context->flush();
14215e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        for (int i = 0; i < 10; ++i) {
1422f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips            TestResource* r = new TestResource(gpu);
14235e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            GrUniqueKey k;
14245e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            make_unique_key<1>(&k, i);
14255e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            r->resourcePriv().setUniqueKey(k);
14265e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon            r->unref();
14275e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        }
14285e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
14295e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        context->flush();
14305e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 10 == cache->getResourceCount());
14315e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        cache->purgeResourcesNotUsedSince(nowish());
14325e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
14335e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    }
14345e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon}
14355e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon
14365480a18d8799511034d0da219c72932cd8f25274Derek Sollenbergerstatic void test_partial_purge(skiatest::Reporter* reporter) {
14375480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    Mock mock(6, 100);
14385480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    GrContext* context = mock.context();
14395480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    GrResourceCache* cache = mock.cache();
1440f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
14415480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14425480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    enum TestsCase {
14435480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kOnlyScratch_TestCase = 0,
14445480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kPartialScratch_TestCase = 1,
14455480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kAllScratch_TestCase = 2,
14465480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kPartial_TestCase = 3,
14475480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kAll_TestCase = 4,
14485480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kNone_TestCase = 5,
14495480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        kEndTests_TestCase = kNone_TestCase + 1
14505480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    };
14515480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14525480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    for (int testCase = 0; testCase < kEndTests_TestCase; testCase++) {
14535480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14545480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        GrUniqueKey key1, key2, key3;
14555480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key1, 1);
14565480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key2, 2);
14575480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        make_unique_key<0>(&key3, 3);
14585480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14595480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add three unique resources to the cache.
1460f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource *unique1 = new TestResource(gpu);
1461f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource *unique2 = new TestResource(gpu);
1462f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource *unique3 = new TestResource(gpu);
14635480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14645480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->resourcePriv().setUniqueKey(key1);
14655480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->resourcePriv().setUniqueKey(key2);
14665480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->resourcePriv().setUniqueKey(key3);
14675480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14685480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->setSize(10);
14695480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->setSize(11);
14705480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->setSize(12);
14715480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14725480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add two scratch resources to the cache.
1473f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource *scratch1 = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
14745480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                                                             TestResource::kA_SimulatedProperty);
1475f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        TestResource *scratch2 = TestResource::CreateScratch(gpu, SkBudgeted::kYes,
14765480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                                                             TestResource::kB_SimulatedProperty);
14775480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch1->setSize(13);
14785480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch2->setSize(14);
14795480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14805480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14815480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
14825480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
14835480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
14845480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14855480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // Add resources to the purgeable queue
14865480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique1->unref();
14875480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch1->unref();
14885480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique2->unref();
14895480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        scratch2->unref();
14905480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        unique3->unref();
14915480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14925480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
14935480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
14945480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
14955480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
14965480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        switch(testCase) {
14975480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kOnlyScratch_TestCase: {
14985480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(14, true);
14995480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
15005480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 33 == cache->getBudgetedResourceBytes());
15015480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
15025480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
15035480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kPartialScratch_TestCase: {
15045480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(3, true);
15055480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 4 == cache->getBudgetedResourceCount());
15065480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 47 == cache->getBudgetedResourceBytes());
15075480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
15085480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
15095480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kAllScratch_TestCase: {
15105480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(50, true);
15115480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
15125480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
15135480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
15145480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
15155480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kPartial_TestCase: {
15165480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(13, false);
15175480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 3 == cache->getBudgetedResourceCount());
15185480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 37 == cache->getBudgetedResourceBytes());
15195480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
15205480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
15215480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kAll_TestCase: {
15225480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(50, false);
15235480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
15245480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
15255480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
15265480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
15275480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            case kNone_TestCase: {
15285480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(0, true);
15295480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                context->purgeUnlockedResources(0, false);
15305480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 5 == cache->getBudgetedResourceCount());
15315480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 60 == cache->getBudgetedResourceBytes());
15325480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                REPORTER_ASSERT(reporter, 60 == cache->getPurgeableBytes());
15335480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger                break;
15345480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger            }
15355480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        };
15365480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
15375480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        // ensure all are purged before the next
15385480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        context->purgeAllUnlockedResources();
15395480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
15405480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger        REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes());
15415480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
15425480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    }
15435480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger}
15445480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger
154510e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_large_resource_count(skiatest::Reporter* reporter) {
154610e23caea3106be125acea10a637789e5a15c728bsalomon    // Set the cache size to double the resource count because we're going to create 2x that number
154710e23caea3106be125acea10a637789e5a15c728bsalomon    // resources, using two different key domains. Add a little slop to the bytes because we resize
154810e23caea3106be125acea10a637789e5a15c728bsalomon    // down to 1 byte after creating the resource.
1549c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    static const int kResourceCnt = 2000;
155010e23caea3106be125acea10a637789e5a15c728bsalomon
1551c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
1552c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
15530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
1554f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
155510e23caea3106be125acea10a637789e5a15c728bsalomon
155610e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
15578718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
15588718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
15598718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
156024db3b1c35fb935660229da164fc5ad31977387fbsalomon
156110e23caea3106be125acea10a637789e5a15c728bsalomon        TestResource* resource;
156210e23caea3106be125acea10a637789e5a15c728bsalomon
1563f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        resource = new TestResource(gpu);
15648718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key1);
156510e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
156610e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
156710e23caea3106be125acea10a637789e5a15c728bsalomon
1568f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        resource = new TestResource(gpu);
15698718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key2);
157010e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
157110e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
157210e23caea3106be125acea10a637789e5a15c728bsalomon    }
157310e23caea3106be125acea10a637789e5a15c728bsalomon
157410e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
1575ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 2 * kResourceCnt);
15760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 2 * kResourceCnt);
15770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 2 * kResourceCnt);
15780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 2 * kResourceCnt);
15790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 2 * kResourceCnt);
158010e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
15818718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
15828718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
15838718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
158424db3b1c35fb935660229da164fc5ad31977387fbsalomon
15858718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
15868718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
158710e23caea3106be125acea10a637789e5a15c728bsalomon    }
158810e23caea3106be125acea10a637789e5a15c728bsalomon
15890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
159010e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
1591ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger    REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 0);
15920ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 0);
15930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 0);
15940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 0);
15950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 0);
159610e23caea3106be125acea10a637789e5a15c728bsalomon
159710e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
15988718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
15998718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
16008718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
160124db3b1c35fb935660229da164fc5ad31977387fbsalomon
16028718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
16038718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
160410e23caea3106be125acea10a637789e5a15c728bsalomon    }
160510e23caea3106be125acea10a637789e5a15c728bsalomon}
160610e23caea3106be125acea10a637789e5a15c728bsalomon
160784cd621670a357484e1674e06d3d8d6f929a4ab2senorblancostatic void test_custom_data(skiatest::Reporter* reporter) {
160884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key1, key2;
160984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key1, 1);
161084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key2, 2);
161184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    int foo = 4132;
161238d909ec2875f79952de08f36adfaac5680d2c53bungeman    key1.setCustomData(SkData::MakeWithCopy(&foo, sizeof(foo)));
161384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key1.getCustomData()->data() == 4132);
161484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, key2.getCustomData() == nullptr);
161584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
161684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    // Test that copying a key also takes a ref on its custom data.
161784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3 = key1;
161884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132);
161984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco}
162084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
1621c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomonstatic void test_abandoned(skiatest::Reporter* reporter) {
1622c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    Mock mock(10, 300);
1623c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrContext* context = mock.context();
1624f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
1625f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips
1626f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    sk_sp<GrGpuResource> resource(new TestResource(gpu));
1627c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    context->abandonContext();
1628c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1629c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    REPORTER_ASSERT(reporter, resource->wasDestroyed());
1630c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1631c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    // Call all the public methods on resource in the abandoned state. They shouldn't crash.
1632c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
16338abb370aca280516f4861c6c942ec453aad018farobertphillips    resource->uniqueID();
1634c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getUniqueKey();
1635c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->wasDestroyed();
1636c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->gpuMemorySize();
1637c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getContext();
1638c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1639c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->abandon();
1640c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().getScratchKey();
1641c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().isBudgeted();
1642c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeBudgeted();
1643c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeUnbudgeted();
1644c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeScratchKey();
1645c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrUniqueKey key;
1646c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    make_unique_key<0>(&key, 1);
1647c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().setUniqueKey(key);
1648c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeUniqueKey();
1649c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon}
1650c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
16511090da6433db575d59b93aec99f6bda49b808b84Brian Salomonstatic void test_tags(skiatest::Reporter* reporter) {
16521090da6433db575d59b93aec99f6bda49b808b84Brian Salomon#ifdef SK_DEBUG
16531090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    // We will insert 1 resource with tag "tag1", 2 with "tag2", and so on, up through kLastTagIdx.
16541090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    static constexpr int kLastTagIdx = 10;
16551090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    static constexpr int kNumResources = kLastTagIdx * (kLastTagIdx + 1) / 2;
16561090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
16571090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    Mock mock(kNumResources, kNumResources * TestResource::kDefaultSize);
16581090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrContext* context = mock.context();
16591090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    GrResourceCache* cache = mock.cache();
1660f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips    GrGpu* gpu = context->contextPriv().getGpu();
16611090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
166267914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger    // tag strings are expected to be long lived
166367914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger    std::vector<SkString> tagStrings;
166467914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger
16651090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkString tagStr;
16661090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    int tagIdx = 0;
16671090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    int currTagCnt = 0;
16681090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
16691090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    for (int i = 0; i < kNumResources; ++i, ++currTagCnt) {
167067914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger
1671f35fd8d2f26ef7217368d1a09d231ee68ed0cb2fRobert Phillips        sk_sp<GrGpuResource> resource(new TestResource(gpu));
16721090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        GrUniqueKey key;
16731090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        if (currTagCnt == tagIdx) {
16741090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            tagIdx += 1;
16751090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            currTagCnt = 0;
16761090da6433db575d59b93aec99f6bda49b808b84Brian Salomon            tagStr.printf("tag%d", tagIdx);
167767914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger            tagStrings.emplace_back(tagStr);
16781090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        }
167967914ebddfc81b5f564dfa119eca3c8bad33db74Derek Sollenberger        make_unique_key<1>(&key, i, tagStrings.back().c_str());
16801090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        resource->resourcePriv().setUniqueKey(key);
16811090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    }
16821090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkASSERT(kLastTagIdx == tagIdx);
16831090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    SkASSERT(currTagCnt == kLastTagIdx);
16841090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
16851090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    // Test i = 0 to exercise unused tag string.
16861090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    for (int i = 0; i <= kLastTagIdx; ++i) {
16871090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        tagStr.printf("tag%d", i);
16881090da6433db575d59b93aec99f6bda49b808b84Brian Salomon        REPORTER_ASSERT(reporter, cache->countUniqueKeysWithTag(tagStr.c_str()) == i);
16891090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    }
16901090da6433db575d59b93aec99f6bda49b808b84Brian Salomon#endif
16911090da6433db575d59b93aec99f6bda49b808b84Brian Salomon}
16921090da6433db575d59b93aec99f6bda49b808b84Brian Salomon
1693dcfca431e3c350e17eedb3402cc63577cea8d4eaBrian SalomonDEF_GPUTEST(ResourceCacheMisc, reporter, /* options */) {
16948b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // The below tests create their own mock contexts.
169571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_no_key(reporter);
169647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips    test_purge_unlocked(reporter);
169784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    test_budgeting(reporter);
16985236cf480daf82b2f36e42795abdbbc915533a59bsalomon    test_unbudgeted(reporter);
1699c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    test_unbudgeted_to_scratch(reporter);
17008718aafec239c93485e45bbe8fed19d9a8def079bsalomon    test_duplicate_unique_key(reporter);
17018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_duplicate_scratch_key(reporter);
170210e23caea3106be125acea10a637789e5a15c728bsalomon    test_remove_scratch_key(reporter);
17031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    test_scratch_key_consistency(reporter);
17048b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_purge_invalidated(reporter);
170571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_cache_chained_purge(reporter);
17068b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_resource_size_changed(reporter);
1707ddf30e64fe474847b204d7062fad3341d245062cbsalomon    test_timestamp_wrap(reporter);
17083f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    test_flush(reporter);
17095e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon    test_time_purge(reporter);
17105480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger    test_partial_purge(reporter);
171110e23caea3106be125acea10a637789e5a15c728bsalomon    test_large_resource_count(reporter);
171284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    test_custom_data(reporter);
1713c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    test_abandoned(reporter);
17141090da6433db575d59b93aec99f6bda49b808b84Brian Salomon    test_tags(reporter);
1715c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
1716c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
1717d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips////////////////////////////////////////////////////////////////////////////////
171832342f032e1dfd133040324f851f0365f9d4cb51Brian Osmanstatic sk_sp<GrTexture> make_normal_texture(GrResourceProvider* provider,
1719d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            GrSurfaceFlags flags,
1720d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            int width, int height,
1721d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips                                            int sampleCnt) {
1722d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrSurfaceDesc desc;
1723d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fFlags = flags;
1724b0e93a22bbfad05bb834e33387880ece56e0f6d2Robert Phillips    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1725d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fWidth = width;
1726d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fHeight = height;
1727d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
1728d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fSampleCnt = sampleCnt;
1729d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1730e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    return provider->createTexture(desc, SkBudgeted::kYes);
1731d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1732d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
17330bd24dc41f2351d84f5fce32130668a5792d134bRobert Phillipsstatic sk_sp<GrTextureProxy> make_mipmap_proxy(GrProxyProvider* proxyProvider,
1734e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               GrSurfaceFlags flags,
1735e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               int width, int height,
1736e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips                                               int sampleCnt) {
1737d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrSurfaceDesc desc;
1738d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fFlags = flags;
1739e44ef10ebbc7f64b627a9ac3a562bd87b3001b0cRobert Phillips    desc.fOrigin = (flags & kRenderTarget_GrSurfaceFlag) ? kBottomLeft_GrSurfaceOrigin
1740e44ef10ebbc7f64b627a9ac3a562bd87b3001b0cRobert Phillips                                                         : kTopLeft_GrSurfaceOrigin;
1741d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fWidth = width;
1742d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fHeight = height;
1743d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fConfig = kRGBA_8888_GrPixelConfig;
1744d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    desc.fSampleCnt = sampleCnt;
1745d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1746308150821517a4dc73e43db1022d3e8bd589d2dbGreg Daniel    return proxyProvider->createMipMapProxy(desc, SkBudgeted::kYes);
1747d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1748d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1749d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips// Exercise GrSurface::gpuMemorySize for different combos of MSAA, RT-only,
1750d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips// Texture-only, both-RT-and-Texture and MIPmapped
1751d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert PhillipsDEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) {
1752d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    GrContext* context = ctxInfo.grContext();
17531afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
17546be756b673b823881e90a2ef68c12b640ddde549Robert Phillips    GrResourceProvider* resourceProvider = context->contextPriv().resourceProvider();
1755d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1756d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    static const int kSize = 64;
1757d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1758d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    // Normal versions
1759e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    {
1760e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        sk_sp<GrTexture> tex;
1761e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
1762bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        tex = make_normal_texture(resourceProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 1);
1763e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size_t size = tex->gpuMemorySize();
1764e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
1765e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
1766bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        size_t sampleCount =
1767bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon                (size_t)context->caps()->getRenderTargetSampleCount(4, kRGBA_8888_GrPixelConfig);
176881e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        if (sampleCount >= 4) {
17691afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips            tex = make_normal_texture(resourceProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
177081e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                                      sampleCount);
1771e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            size = tex->gpuMemorySize();
177281e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel            REPORTER_ASSERT(reporter,
177381e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4 == size ||                  // msaa4 failed
177481e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4*sampleCount == size ||      // auto-resolving
177581e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                            kSize*kSize*4*(sampleCount+1) == size);   // explicit resolve buffer
1776e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        }
1777d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1778bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        tex = make_normal_texture(resourceProvider, kNone_GrSurfaceFlags, kSize, kSize, 1);
1779d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips        size = tex->gpuMemorySize();
1780e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4 == size);
1781d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    }
1782d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1783d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1784d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips    // Mipmapped versions
178548c9919335c7da6188c08a78552186760bd434eaBrian Osman    if (context->caps()->mipMapSupport()) {
1786e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        sk_sp<GrTextureProxy> proxy;
1787d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1788bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        proxy = make_mipmap_proxy(proxyProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 1);
1789e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size_t size = proxy->gpuMemorySize();
1790e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
1791e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips
1792bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        size_t sampleCount =
1793bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon                (size_t)context->caps()->getRenderTargetSampleCount(4, kRGBA_8888_GrPixelConfig);
179481e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel        if (sampleCount >= 4) {
17951afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips            proxy = make_mipmap_proxy(proxyProvider, kRenderTarget_GrSurfaceFlag, kSize, kSize,
179681e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel                                      sampleCount);
1797e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            size = proxy->gpuMemorySize();
1798e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips            REPORTER_ASSERT(reporter,
179981e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4+(kSize*kSize*4)/3 == size ||                 // msaa4 failed
180081e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4*sampleCount+(kSize*kSize*4)/3 == size ||     // auto-resolving
180181e7bf8d6d338d944f3c5075b14c21580398aeb6Greg Daniel               kSize*kSize*4*(sampleCount+1)+(kSize*kSize*4)/3 == size);  // explicit resolve buffer
1802e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        }
18031b35256f1166358056b2aad8ce09caa6f07912d5Robert Phillips
1804bdecacfbe47bc7211336bb847bb33c00ef85ea3eBrian Salomon        proxy = make_mipmap_proxy(proxyProvider, kNone_GrSurfaceFlags, kSize, kSize, 1);
1805e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        size = proxy->gpuMemorySize();
1806e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips        REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size);
1807e78b7259c3d5cbed77b4390150cfb699b0b59cd4Robert Phillips    }
1808d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips}
1809d6214d4f4664ce47861dc690b0ddbea3b7a07855Robert Phillips
1810c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#endif
1811