ResourceCacheTest.cpp revision 36352bf5e38f45a70ee4f4fc132a38048d38206d
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
8c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#if SK_SUPPORT_GPU
94ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org
10bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "GrContext.h"
11c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#include "GrContextFactory.h"
12bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "GrGpu.h"
133582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourceCacheAccess.h"
143582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourcePriv.h"
156bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon#include "GrRenderTarget.h"
166bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon#include "GrRenderTargetPriv.h"
170ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#include "GrResourceCache.h"
18bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "SkCanvas.h"
1971cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkGr.h"
2071cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkMessageBus.h"
2169f6f00fd975823e825c5aa0b1b8f4416e7c812breed#include "SkSurface.h"
224ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
23c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
24c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gWidth = 640;
25c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gHeight = 480;
26c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
27c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
28334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonstatic void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanvas* canvas) {
29c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
30c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
31c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap src;
32deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    src.allocN32Pixels(size.width(), size.height());
33c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    src.eraseColor(SK_ColorBLACK);
34c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t srcSize = src.getSize();
35c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
3695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    size_t initialCacheSize;
3795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->getResourceCacheUsage(NULL, &initialCacheSize);
38c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
39c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    int oldMaxNum;
40c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t oldMaxBytes;
4195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
4217f1ae63d57a3f3d3a0ae50e1b25b3f8b18fd328skia.committer@gmail.com
43c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // Set the cache limits so we can fit 10 "src" images and the
44c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // max number of textures doesn't matter
45c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t maxCacheSize = initialCacheSize + 10*srcSize;
4695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(1000, maxCacheSize);
47c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
48c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap readback;
49deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    readback.allocN32Pixels(size.width(), size.height());
50c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
51c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    for (int i = 0; i < 100; ++i) {
52c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        canvas->drawBitmap(src, 0, 0);
53c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        canvas->readPixels(size, &readback);
54c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
55c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // "modify" the src texture
56c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        src.notifyPixelsChanged();
57c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
5895c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        size_t curCacheSize;
5995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        context->getResourceCacheUsage(NULL, &curCacheSize);
60c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
61c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // we should never go over the size limit
62c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
63c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    }
64c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
6595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
66c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
67c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
6802a44a488605112aa6683c9d919e13b188112ce1bsalomonstatic void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* context) {
6902a44a488605112aa6683c9d919e13b188112ce1bsalomon    GrSurfaceDesc smallDesc;
7002a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fFlags = kRenderTarget_GrSurfaceFlag;
7102a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fConfig = kSkia8888_GrPixelConfig;
7202a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fWidth = 4;
7302a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fHeight = 4;
7402a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fSampleCnt = 0;
7502a44a488605112aa6683c9d919e13b188112ce1bsalomon
7602a44a488605112aa6683c9d919e13b188112ce1bsalomon    // Test that two budgeted RTs with the same desc share a stencil buffer.
7702a44a488605112aa6683c9d919e13b188112ce1bsalomon    SkAutoTUnref<GrTexture> smallRT0(context->createTexture(smallDesc, true));
786bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (smallRT0 && smallRT0->asRenderTarget()) {
796bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        smallRT0->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
806bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
816bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
8202a44a488605112aa6683c9d919e13b188112ce1bsalomon    SkAutoTUnref<GrTexture> smallRT1(context->createTexture(smallDesc, true));
836bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (smallRT1 && smallRT1->asRenderTarget()) {
846bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        smallRT1->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
856bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
866bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
8702a44a488605112aa6683c9d919e13b188112ce1bsalomon    REPORTER_ASSERT(reporter, smallRT0 && smallRT1 &&
8802a44a488605112aa6683c9d919e13b188112ce1bsalomon                              smallRT0->asRenderTarget() && smallRT1->asRenderTarget() &&
896bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                              smallRT0->asRenderTarget()->renderTargetPriv().getStencilBuffer() ==
906bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                              smallRT1->asRenderTarget()->renderTargetPriv().getStencilBuffer());
9102a44a488605112aa6683c9d919e13b188112ce1bsalomon
9202a44a488605112aa6683c9d919e13b188112ce1bsalomon    // An unbudgeted RT with the same desc should also share.
9302a44a488605112aa6683c9d919e13b188112ce1bsalomon    SkAutoTUnref<GrTexture> smallRT2(context->createTexture(smallDesc, false));
946bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (smallRT2 && smallRT2->asRenderTarget()) {
956bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        smallRT2->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
966bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
9702a44a488605112aa6683c9d919e13b188112ce1bsalomon    REPORTER_ASSERT(reporter, smallRT0 && smallRT2 &&
9802a44a488605112aa6683c9d919e13b188112ce1bsalomon                              smallRT0->asRenderTarget() && smallRT2->asRenderTarget() &&
996bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                              smallRT0->asRenderTarget()->renderTargetPriv().getStencilBuffer() ==
1006bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                              smallRT2->asRenderTarget()->renderTargetPriv().getStencilBuffer());
10102a44a488605112aa6683c9d919e13b188112ce1bsalomon
10202a44a488605112aa6683c9d919e13b188112ce1bsalomon    // An RT with a much larger size should not share.
10302a44a488605112aa6683c9d919e13b188112ce1bsalomon    GrSurfaceDesc bigDesc;
10402a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fFlags = kRenderTarget_GrSurfaceFlag;
10502a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fConfig = kSkia8888_GrPixelConfig;
10602a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fWidth = 400;
10702a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fHeight = 200;
10802a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fSampleCnt = 0;
10902a44a488605112aa6683c9d919e13b188112ce1bsalomon    SkAutoTUnref<GrTexture> bigRT(context->createTexture(bigDesc, false));
1106bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (bigRT && bigRT->asRenderTarget()) {
1116bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        bigRT->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
1126bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
11302a44a488605112aa6683c9d919e13b188112ce1bsalomon    REPORTER_ASSERT(reporter, smallRT0 && bigRT &&
11402a44a488605112aa6683c9d919e13b188112ce1bsalomon                              smallRT0->asRenderTarget() && bigRT->asRenderTarget() &&
1156bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                              smallRT0->asRenderTarget()->renderTargetPriv().getStencilBuffer() !=
1166bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                              bigRT->asRenderTarget()->renderTargetPriv().getStencilBuffer());
11702a44a488605112aa6683c9d919e13b188112ce1bsalomon
11802a44a488605112aa6683c9d919e13b188112ce1bsalomon    if (context->getMaxSampleCount() >= 4) {
11902a44a488605112aa6683c9d919e13b188112ce1bsalomon        // An RT with a different sample count should not share.
12002a44a488605112aa6683c9d919e13b188112ce1bsalomon        GrSurfaceDesc smallMSAADesc = smallDesc;
12102a44a488605112aa6683c9d919e13b188112ce1bsalomon        smallMSAADesc.fSampleCnt = 4;
12202a44a488605112aa6683c9d919e13b188112ce1bsalomon        SkAutoTUnref<GrTexture> smallMSAART0(context->createTexture(smallMSAADesc, false));
1236bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        if (smallMSAART0 && smallMSAART0->asRenderTarget()) {
1246bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            smallMSAART0->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
1256bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        }
126b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#ifdef SK_BUILD_FOR_ANDROID
127b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        if (!smallMSAART0) {
128b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            // The nexus player seems to fail to create MSAA textures.
129b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            return;
130b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        }
131b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#endif
1326bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        REPORTER_ASSERT(reporter,
1336bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallRT0 && smallMSAART0 &&
1346bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallRT0->asRenderTarget() && smallMSAART0->asRenderTarget() &&
1356bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallRT0->asRenderTarget()->renderTargetPriv().getStencilBuffer() !=
1366bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilBuffer());
13702a44a488605112aa6683c9d919e13b188112ce1bsalomon        // A second MSAA RT should share with the first MSAA RT.
13802a44a488605112aa6683c9d919e13b188112ce1bsalomon        SkAutoTUnref<GrTexture> smallMSAART1(context->createTexture(smallMSAADesc, false));
1396bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
1406bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            smallMSAART1->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
1416bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        }
1426bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        REPORTER_ASSERT(reporter,
1436bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART0 && smallMSAART1 &&
1446bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART0->asRenderTarget() &&
1456bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART1->asRenderTarget() &&
1466bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilBuffer() ==
1476bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART1->asRenderTarget()->renderTargetPriv().getStencilBuffer());
14802a44a488605112aa6683c9d919e13b188112ce1bsalomon        // But not one with a larger sample count should not. (Also check that the request for 4
14902a44a488605112aa6683c9d919e13b188112ce1bsalomon        // samples didn't get rounded up to >= 8 or else they could share.).
15002a44a488605112aa6683c9d919e13b188112ce1bsalomon        if (context->getMaxSampleCount() >= 8 && smallMSAART0 && smallMSAART0->asRenderTarget() &&
15102a44a488605112aa6683c9d919e13b188112ce1bsalomon            smallMSAART0->asRenderTarget()->numSamples() < 8) {
15202a44a488605112aa6683c9d919e13b188112ce1bsalomon            smallMSAADesc.fSampleCnt = 8;
15302a44a488605112aa6683c9d919e13b188112ce1bsalomon            smallMSAART1.reset(context->createTexture(smallMSAADesc, false));
1546bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            SkAutoTUnref<GrTexture> smallMSAART1(context->createTexture(smallMSAADesc, false));
1556bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
1566bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                smallMSAART1->asRenderTarget()->renderTargetPriv().attachStencilBuffer();
1576bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            }
1586bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            REPORTER_ASSERT(reporter,
1596bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                            smallMSAART0 && smallMSAART1 &&
1606bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                            smallMSAART0->asRenderTarget() &&
1616bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                            smallMSAART1->asRenderTarget() &&
1626bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                            smallMSAART0->asRenderTarget()->renderTargetPriv().getStencilBuffer() !=
1636bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                            smallMSAART1->asRenderTarget()->renderTargetPriv().getStencilBuffer());
16402a44a488605112aa6683c9d919e13b188112ce1bsalomon        }
16502a44a488605112aa6683c9d919e13b188112ce1bsalomon    }
16602a44a488605112aa6683c9d919e13b188112ce1bsalomon}
16702a44a488605112aa6683c9d919e13b188112ce1bsalomon
1686d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomonclass TestResource : public GrGpuResource {
16911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    static const size_t kDefaultSize = 100;
1701c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    enum ScratchConstructor { kScratchConstructor };
171c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgpublic:
172c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    SK_DECLARE_INST_COUNT(TestResource);
1731c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    /** Property that distinctly categorizes the resource.
1741c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon     * For example, textures have width, height, ... */
17523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
1761c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
1775236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
1785236cf480daf82b2f36e42795abdbbc915533a59bsalomon        : INHERITED(gpu, lifeCycle)
1795236cf480daf82b2f36e42795abdbbc915533a59bsalomon        , fToDelete(NULL)
1801c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(size)
18123e619cf462b2a8a500f3ca750e099f79601f508bsalomon        , fProperty(kA_SimulatedProperty) {
1825236cf480daf82b2f36e42795abdbbc915533a59bsalomon        ++fNumAlive;
1835236cf480daf82b2f36e42795abdbbc915533a59bsalomon        this->registerWithCache();
1845236cf480daf82b2f36e42795abdbbc915533a59bsalomon    }
1855236cf480daf82b2f36e42795abdbbc915533a59bsalomon
1865236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource(GrGpu* gpu, GrGpuResource::LifeCycle lifeCycle)
1875236cf480daf82b2f36e42795abdbbc915533a59bsalomon        : INHERITED(gpu, lifeCycle)
188dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon        , fToDelete(NULL)
1891c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
19023e619cf462b2a8a500f3ca750e099f79601f508bsalomon        , fProperty(kA_SimulatedProperty) {
191dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon        ++fNumAlive;
192dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon        this->registerWithCache();
193dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    }
194dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
1958b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    TestResource(GrGpu* gpu)
1965236cf480daf82b2f36e42795abdbbc915533a59bsalomon        : INHERITED(gpu, kCached_LifeCycle)
19711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        , fToDelete(NULL)
1981c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
19923e619cf462b2a8a500f3ca750e099f79601f508bsalomon        , fProperty(kA_SimulatedProperty) {
2008b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        ++fNumAlive;
2018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        this->registerWithCache();
2028b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
2038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
20423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    static TestResource* CreateScratch(GrGpu* gpu, SimulatedProperty property, bool cached = true) {
205c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        return SkNEW_ARGS(TestResource, (gpu, property, cached, kScratchConstructor));
206c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
207c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
208c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    ~TestResource() {
209334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon        --fNumAlive;
21071cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkSafeUnref(fToDelete);
211c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
212c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
21311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void setSize(size_t size) {
21411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        fSize = size;
21511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        this->didChangeGpuMemorySize();
21611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
21711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
218334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int NumAlive() { return fNumAlive; }
219c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
22071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setUnrefWhenDestroyed(TestResource* resource) {
22171cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkRefCnt_SafeAssign(fToDelete, resource);
222c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
223c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
2241c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
2251c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
2261c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
22724db3b1c35fb935660229da164fc5ad31977387fbsalomon        for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
22824db3b1c35fb935660229da164fc5ad31977387fbsalomon            builder[i] = static_cast<uint32_t>(i + property);
2291c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        }
2301c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
2311c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2321c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static size_t ExpectedScratchKeySize() {
2331c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
2341c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
2351c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
236c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgprivate:
23724db3b1c35fb935660229da164fc5ad31977387fbsalomon    static const int kScratchKeyFieldCnt = 6;
2381c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
239c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource(GrGpu* gpu, SimulatedProperty property, bool cached, ScratchConstructor)
240c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        : INHERITED(gpu, cached ? kCached_LifeCycle : kUncached_LifeCycle)
2411c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fToDelete(NULL)
2421c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
2431c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fProperty(property) {
2441c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey scratchKey;
2451c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ComputeScratchKey(fProperty, &scratchKey);
2461c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        this->setScratchKey(scratchKey);
2471c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ++fNumAlive;
2481c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        this->registerWithCache();
2491c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
2501c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
25136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t onGpuMemorySize() const override { return fSize; }
25269ed47f42d4877c178fdc0031cb01af2966ae235bsalomon
253c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    TestResource* fToDelete;
25411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    size_t fSize;
255334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int fNumAlive;
2561c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    SimulatedProperty fProperty;
2576d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    typedef GrGpuResource INHERITED;
258c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org};
259334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonint TestResource::fNumAlive = 0;
260c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
261c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonclass Mock {
262c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonpublic:
263c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock(int maxCnt, size_t maxBytes) {
264c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext.reset(GrContext::CreateMockContext());
265c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        SkASSERT(fContext);
266c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext->setResourceCacheLimits(maxCnt, maxBytes);
2670ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = fContext->getResourceCache();
2680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        cache->purgeAllUnlocked();
2690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
27071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
271c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
2720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache() { return fContext->getResourceCache(); }
273c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
274c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context() { return fContext; }
275c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
276c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonprivate:
277c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    SkAutoTUnref<GrContext> fContext;
278c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon};
279c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
280c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_no_key(skiatest::Reporter* reporter) {
281c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
282c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
2830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
28471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
28571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Create a bunch of resources with no keys
2865236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
2875236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
2885236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* c = SkNEW_ARGS(TestResource, (context->getGpu()));
2895236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* d = SkNEW_ARGS(TestResource, (context->getGpu()));
29071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->setSize(11);
29171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->setSize(12);
29271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->setSize(13);
29371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->setSize(14);
29471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
29571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
2960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
29771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
2980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              d->gpuMemorySize() == cache->getResourceBytes());
29971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
30071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Should be safe to purge without deleting the resources since we still have refs.
3010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
30271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
30371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3048718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Since the resources have neither unique nor scratch keys, delete immediately upon unref.
30571cb0c241e439b6ed746b90294d0b6916644a644bsalomon
30671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->unref();
30771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
3080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
30971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
3100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
31171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
31271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->unref();
31371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
3140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
31571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
3160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
31771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
31871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->unref();
31971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
3200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
3210ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
32271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
32371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->unref();
32471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
3250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
3260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
32771cb0c241e439b6ed746b90294d0b6916644a644bsalomon}
32871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
32924db3b1c35fb935660229da164fc5ad31977387fbsalomon// Each integer passed as a template param creates a new domain.
3308718aafec239c93485e45bbe8fed19d9a8def079bsalomontemplate <int> static void make_unique_key(GrUniqueKey* key, int data) {
3318718aafec239c93485e45bbe8fed19d9a8def079bsalomon    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
3328718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey::Builder builder(key, d, 1);
33324db3b1c35fb935660229da164fc5ad31977387fbsalomon    builder[0] = data;
33424db3b1c35fb935660229da164fc5ad31977387fbsalomon}
33524db3b1c35fb935660229da164fc5ad31977387fbsalomon
33684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomonstatic void test_budgeting(skiatest::Reporter* reporter) {
337c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
338c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
3390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
340dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
3418718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
3428718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
343dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
3448718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create a scratch, a unique, and a wrapped resource
3451c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    TestResource* scratch =
34623e619cf462b2a8a500f3ca750e099f79601f508bsalomon            TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
347dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(10);
3488718aafec239c93485e45bbe8fed19d9a8def079bsalomon    TestResource* unique = SkNEW_ARGS(TestResource, (context->getGpu()));
3498718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
350f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
3515236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* wrapped = SkNEW_ARGS(TestResource,
3525236cf480daf82b2f36e42795abdbbc915533a59bsalomon                                       (context->getGpu(), GrGpuResource::kWrapped_LifeCycle));
3535236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->setSize(12);
3545236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* unbudgeted = SkNEW_ARGS(TestResource,
3555236cf480daf82b2f36e42795abdbbc915533a59bsalomon                                          (context->getGpu(), GrGpuResource::kUncached_LifeCycle));
35684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->setSize(13);
357dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
3588718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Make sure we can't add a unique key to the wrapped resource
3598718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey2;
3608718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey2, 1);
361f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    wrapped->resourcePriv().setUniqueKey(uniqueKey2);
3628718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, NULL == cache->findAndRefUniqueResource(uniqueKey2));
363dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
364dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Make sure sizes are as we expect
3650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
3668718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
36784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
3680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
3690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
3708718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
3710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
372dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
37363c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
3740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
3750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
3768718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
37784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
3780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
3790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
3808718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
3810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
382dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
383dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Unreffing the wrapped resource should free it right away.
384dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
3850ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
3868718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
3870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
388dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
38984c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    // Now try freeing the budgeted resources first
3905236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped = SkNEW_ARGS(TestResource, (context->getGpu(), GrGpuResource::kWrapped_LifeCycle));
391dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(12);
3928718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
3930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
3940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
39584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
3960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
3970ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
3980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes());
399dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
400dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->unref();
4010ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4020ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
40384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
4040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
407dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
408dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
4090ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes());
4110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
41384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
41484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->unref();
4150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
4160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
4170ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4180ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
419dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon}
420dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4215236cf480daf82b2f36e42795abdbbc915533a59bsalomonstatic void test_unbudgeted(skiatest::Reporter* reporter) {
422c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
423c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
4240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
4255236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4268718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
4278718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
4285236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4295236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* scratch;
4308718aafec239c93485e45bbe8fed19d9a8def079bsalomon    TestResource* unique;
4315236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* wrapped;
4325236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* unbudgeted;
4335236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4345236cf480daf82b2f36e42795abdbbc915533a59bsalomon    // A large uncached or wrapped resource shouldn't evict anything.
43523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    scratch = TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
4365236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->setSize(10);
4375236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->unref();
4380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes());
4400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
4410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes());
4425236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4438718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique = SkNEW_ARGS(TestResource, (context->getGpu()));
4448718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
445f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
4468718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
4470ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
4480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
4490ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
4515236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    size_t large = 2 * cache->getResourceBytes();
4535236cf480daf82b2f36e42795abdbbc915533a59bsalomon    unbudgeted = SkNEW_ARGS(TestResource,
4545236cf480daf82b2f36e42795abdbbc915533a59bsalomon                            (context->getGpu(), large, GrGpuResource::kUncached_LifeCycle));
4550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
4560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
4570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
4595236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4605236cf480daf82b2f36e42795abdbbc915533a59bsalomon    unbudgeted->unref();
4610ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
4620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
4630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
4655236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4665236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped = SkNEW_ARGS(TestResource,
4675236cf480daf82b2f36e42795abdbbc915533a59bsalomon                         (context->getGpu(), large, GrGpuResource::kWrapped_LifeCycle));
4680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
4690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
4700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
4725236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4735236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->unref();
4740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
4750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
4760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
4780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon
4790ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
4810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
4820ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
4845236cf480daf82b2f36e42795abdbbc915533a59bsalomon}
4855236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4863582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon// This method can't be static because it needs to friended in GrGpuResource::CacheAccess.
4873582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomonvoid test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
4883582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon/*static*/ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
489c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
490c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
4910ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
492c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
493c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* resource =
49423e619cf462b2a8a500f3ca750e099f79601f508bsalomon        TestResource::CreateScratch(context->getGpu(), TestResource::kA_SimulatedProperty, false);
495c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrScratchKey key;
49623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
497c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
498c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    size_t size = resource->gpuMemorySize();
499c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    for (int i = 0; i < 2; ++i) {
500c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Since this resource is unbudgeted, it should not be reachable as scratch.
5013582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
502c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
5033582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, !resource->resourcePriv().isBudgeted());
5040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, NULL == cache->findAndRefScratchResource(key));
5050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
5070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
509c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
510c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Once it is unrefed, it should become available as scratch.
511c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        resource->unref();
5120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
5140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
5160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        resource = static_cast<TestResource*>(cache->findAndRefScratchResource(key));
517c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource);
5183582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
519c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
5203582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().isBudgeted());
521c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
522c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        if (0 == i) {
523c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
524c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // the above tests again.
5253582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().makeUnbudgeted();
526c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        } else {
527c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // After the second time around, try removing the scratch key
5283582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().removeScratchKey();
5290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
5310ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
5333582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid());
534c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
5353582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, resource->resourcePriv().isBudgeted());
536c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
537c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // now when it is unrefed it should die since it has no key.
538c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            resource->unref();
5390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5410ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
543c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        }
5448b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
545c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon}
546c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
547c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
548c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
549c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
5518b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
5528b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Create two resources that have the same scratch key.
55323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
55423e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
55523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
55623e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
5578b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
5588b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->setSize(12);
5591c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
56023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
5611c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Check for negative case consistency. (leaks upon test failure.)
5620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, NULL == cache->findAndRefScratchResource(scratchKey1));
5631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
5641c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
56523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
5661c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
5670ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
568ac49acda520292b059bc37fd368dff912626c3d9bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
5690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
5700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
57171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
5720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
5738b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
57463c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
5750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5768b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
5770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5788b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
5798b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Unref but don't purge
5808b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->unref();
5818b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
5828b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
5830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
5848b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
58563c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Purge again. This time resources should be purgeable.
5860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5878b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
5880ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
5908b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
5918b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
59210e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_remove_scratch_key(skiatest::Reporter* reporter) {
593c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
594c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5950ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
59610e23caea3106be125acea10a637789e5a15c728bsalomon
59710e23caea3106be125acea10a637789e5a15c728bsalomon    // Create two resources that have the same scratch key.
59823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
59923e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
60023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
60123e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
60210e23caea3106be125acea10a637789e5a15c728bsalomon    a->unref();
60310e23caea3106be125acea10a637789e5a15c728bsalomon    b->unref();
60410e23caea3106be125acea10a637789e5a15c728bsalomon
6051c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
6061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
60723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
6081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
6090ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey) == NULL);
6101c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
61223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
61310e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
61610e23caea3106be125acea10a637789e5a15c728bsalomon
61710e23caea3106be125acea10a637789e5a15c728bsalomon    // Find the first resource and remove its scratch key
61810e23caea3106be125acea10a637789e5a15c728bsalomon    GrGpuResource* find;
6190ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    find = cache->findAndRefScratchResource(scratchKey);
6203582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
62110e23caea3106be125acea10a637789e5a15c728bsalomon    // It's still alive, but not cached by scratch key anymore
62210e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
6240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
62510e23caea3106be125acea10a637789e5a15c728bsalomon
62610e23caea3106be125acea10a637789e5a15c728bsalomon    // The cache should immediately delete it when it's unrefed since it isn't accessible.
62710e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
62810e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
6290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
6300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
63110e23caea3106be125acea10a637789e5a15c728bsalomon
63210e23caea3106be125acea10a637789e5a15c728bsalomon    // Repeat for the second resource.
6330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    find = cache->findAndRefScratchResource(scratchKey);
6343582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
63510e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
6360ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
6370ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
63810e23caea3106be125acea10a637789e5a15c728bsalomon
63910e23caea3106be125acea10a637789e5a15c728bsalomon    // Should be able to call this multiple times with no problem.
6403582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
64110e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
6420ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
6430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
64410e23caea3106be125acea10a637789e5a15c728bsalomon
64510e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
64610e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
6470ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
6480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
64910e23caea3106be125acea10a637789e5a15c728bsalomon}
65010e23caea3106be125acea10a637789e5a15c728bsalomon
6511c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomonstatic void test_scratch_key_consistency(skiatest::Reporter* reporter) {
652c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
653c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
6540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
6551c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6561c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Create two resources that have the same scratch key.
65723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
65823e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
65923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
66023e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
6611c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    a->unref();
6621c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    b->unref();
6631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6641c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
6651c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key comparison and assignment is consistent.
6661c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
66723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
6681c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey2;
66923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
6701c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
6711c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
6721c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
6731c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey1;
6741c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
6751c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 == scratchKey);
6761c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey1);
6771c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey);
6781c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey2);
6791c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey2;
6801c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
6811c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
6821c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
6831c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
6841c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
6851c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6861c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
68723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
6881c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
6890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey) == NULL);
6901c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6911c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Find the first resource with a scratch key and a copy of a scratch key.
69223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
6930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrGpuResource* find = cache->findAndRefScratchResource(scratchKey);
6941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find != NULL);
6951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
6961c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6971c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey2 = scratchKey;
6980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    find = cache->findAndRefScratchResource(scratchKey2);
6991c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find != NULL);
7001c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find == a || find == b);
7011c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7020ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrGpuResource* find2 = cache->findAndRefScratchResource(scratchKey2);
7031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 != NULL);
7041c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 == a || find2 == b);
7051c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 != find);
7061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find2->unref();
7071c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
7081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon}
7091c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7108718aafec239c93485e45bbe8fed19d9a8def079bsalomonstatic void test_duplicate_unique_key(skiatest::Reporter* reporter) {
711c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
712c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
7148b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
7158718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key;
7168718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key, 0);
717334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
7188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create two resources that we will attempt to register with the same unique key.
7195236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
7208b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
72171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
722f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Set key on resource a.
723f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
724f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
725f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
726f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
727f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Make sure that redundantly setting a's key works.
728f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
729f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
730f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
731f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
732f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache->getResourceBytes());
733f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
734f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
735f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Create resource b and set the same key. It should replace a's unique key cache entry.
736f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
737f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->setSize(12);
738f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->resourcePriv().setUniqueKey(key);
739f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b == cache->findAndRefUniqueResource(key));
740f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->unref();
74171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
742f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Still have two resources because a is still reffed.
7430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
744f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
7458b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
7468b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
747f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
748f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now a should be gone.
749f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
750f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
751f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
752f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
753f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now replace b with c, but make sure c can start with one unique key and change it to b's key.
754f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Also make b be unreffed when replacement occurs.
7558b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
756f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    TestResource* c = SkNEW_ARGS(TestResource, (context->getGpu()));
757f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    GrUniqueKey differentKey;
758f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    make_unique_key<0>(&differentKey, 1);
759f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->setSize(13);
760f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(differentKey);
761f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
762f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() == cache->getResourceBytes());
763f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
764f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c replaces b and b should be immediately purged.
765f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(key);
7660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
767f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
76871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
76971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
770f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c shouldn't be purged because it is ref'ed.
7710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
7720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
773f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
7748b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
7758b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
776f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Drop the ref on c, it should be kept alive because it has a unique key.
777f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
7780ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
779f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
78071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
78171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
782f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Verify that we can find c, then remove its unique key. It should get purged immediately.
783f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c == cache->findAndRefUniqueResource(key));
784f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().removeUniqueKey();
785f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
7860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
7870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
7888b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
7898b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
7908b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
7918b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_purge_invalidated(skiatest::Reporter* reporter) {
792c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
793c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
7958b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
7968718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2, key3;
7978718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
7988718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
7998718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key3, 3);
8008b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
80123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Add three resources to the cache. Only c is usable as scratch.
8025236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
8035236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
80423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* c = TestResource::CreateScratch(context->getGpu(),
80523e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kA_SimulatedProperty);
8068718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
8078718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
8088718aafec239c93485e45bbe8fed19d9a8def079bsalomon    c->resourcePriv().setUniqueKey(key3);
809c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    a->unref();
81023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // hold b until *after* the message is sent.
8118b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    c->unref();
812c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
8138718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
8148718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
8158718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
816334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
81723e619cf462b2a8a500f3ca750e099f79601f508bsalomon
8188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef GrUniqueKeyInvalidatedMessage Msg;
8198718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkMessageBus<GrUniqueKeyInvalidatedMessage> Bus;
82023e619cf462b2a8a500f3ca750e099f79601f508bsalomon
82123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Invalidate two of the three, they should be purged and no longer accessible via their keys.
82223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key1));
82323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key2));
8240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
82523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // a should be deleted now, but we still have a ref on b.
8268718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
8278718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
82823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8298718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
8308b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8318b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Invalidate the third.
83223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key3));
8330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
83423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // we still have a ref on b, c should be recycled as scratch.
83523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8368718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key3));
83771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
83823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // make b purgeable. It should be immediately deleted since it has no key.
83923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    b->unref();
84023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
84123e619cf462b2a8a500f3ca750e099f79601f508bsalomon
84223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Make sure we actually get to c via it's scratch key, before we say goodbye.
84323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    GrScratchKey scratchKey;
84423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
8450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrGpuResource* scratch = cache->findAndRefScratchResource(scratchKey);
84623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, scratch == c);
84723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
84823e619cf462b2a8a500f3ca750e099f79601f508bsalomon
84923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Get rid of c.
8500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
8510ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    scratch = cache->findAndRefScratchResource(scratchKey);
85271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
8530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
8540ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
85523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, !scratch);
85623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
857c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org}
858c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
85971cb0c241e439b6ed746b90294d0b6916644a644bsalomonstatic void test_cache_chained_purge(skiatest::Reporter* reporter) {
860c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(3, 30000);
861c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
8620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
8638b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8648718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
8658718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
8668718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
867bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
868334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
869c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
870c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
8718718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
8728718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
87371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
874c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Make a cycle
875c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->setUnrefWhenDestroyed(b);
876c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->setUnrefWhenDestroyed(a);
877334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
878c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
879334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
880c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->unref();
881c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->unref();
8828b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
883c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8848b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8850ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
886c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
887f21dab95405979a4aff9f6a741c818304a67f220bsalomon
888c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Break the cycle
889c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->setUnrefWhenDestroyed(NULL);
890c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
891ac49acda520292b059bc37fd368dff912626c3d9bsalomon
8920ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
893c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
894bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org}
895bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
8968b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_resource_size_changed(skiatest::Reporter* reporter) {
8978718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
8988718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
8998718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
90011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
90111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test changing resources sizes (both increase & decrease).
90211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
903c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(3, 30000);
904c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
9050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
90611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9075236cf480daf82b2f36e42795abdbbc915533a59bsalomon        TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
9088718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
90911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
91011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9115236cf480daf82b2f36e42795abdbbc915533a59bsalomon        TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
9128718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
91311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
91411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
9160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
9178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
9188718aafec239c93485e45bbe8fed19d9a8def079bsalomon            SkAutoTUnref<TestResource> find2(
9198718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key2)));
9208b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(200);
9218718aafec239c93485e45bbe8fed19d9a8def079bsalomon            SkAutoTUnref<TestResource> find1(
9228718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key1)));
9238b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find1->setSize(50);
9248b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
92511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 250 == cache->getResourceBytes());
9270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
92811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
92911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
93011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test increasing a resources size beyond the cache budget.
93111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
932c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(2, 300);
933c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
9340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
93511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9365236cf480daf82b2f36e42795abdbbc915533a59bsalomon        TestResource* a = SkNEW_ARGS(TestResource, (context->getGpu()));
9378b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        a->setSize(100);
9388718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
93911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
94011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9415236cf480daf82b2f36e42795abdbbc915533a59bsalomon        TestResource* b = SkNEW_ARGS(TestResource, (context->getGpu()));
9428b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        b->setSize(100);
9438718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
94411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
94511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
9470ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
94811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9498b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
9508718aafec239c93485e45bbe8fed19d9a8def079bsalomon            SkAutoTUnref<TestResource> find2(static_cast<TestResource*>(
9518718aafec239c93485e45bbe8fed19d9a8def079bsalomon                cache->findAndRefUniqueResource(key2)));
9528b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(201);
9538b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
9548718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
95511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 201 == cache->getResourceBytes());
9570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
95811c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
95911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org}
96011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
961ddf30e64fe474847b204d7062fad3341d245062cbsalomonstatic void test_timestamp_wrap(skiatest::Reporter* reporter) {
962ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kCount = 50;
963ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetCnt = kCount / 2;
964ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kLockedFreq = 8;
965ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetSize = 0x80000000;
966ddf30e64fe474847b204d7062fad3341d245062cbsalomon
967ddf30e64fe474847b204d7062fad3341d245062cbsalomon    SkRandom random;
968ddf30e64fe474847b204d7062fad3341d245062cbsalomon
969ddf30e64fe474847b204d7062fad3341d245062cbsalomon    // Run the test 2*kCount times;
970ddf30e64fe474847b204d7062fad3341d245062cbsalomon    for (int i = 0; i < 2 * kCount; ++i ) {
971ddf30e64fe474847b204d7062fad3341d245062cbsalomon        Mock mock(kBudgetCnt, kBudgetSize);
972ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrContext* context = mock.context();
973ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrResourceCache* cache = mock.cache();
974ddf30e64fe474847b204d7062fad3341d245062cbsalomon
975ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Pick a random number of resources to add before the timestamp will wrap.
976ddf30e64fe474847b204d7062fad3341d245062cbsalomon        cache->changeTimestamp(SK_MaxU32 - random.nextULessThan(kCount + 1));
977ddf30e64fe474847b204d7062fad3341d245062cbsalomon
978ddf30e64fe474847b204d7062fad3341d245062cbsalomon        static const int kNumToPurge = kCount - kBudgetCnt;
979ddf30e64fe474847b204d7062fad3341d245062cbsalomon
980ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<int> shouldPurgeIdxs;
981ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int purgeableCnt = 0;
982ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<GrGpuResource*> resourcesToUnref;
983ddf30e64fe474847b204d7062fad3341d245062cbsalomon
984ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Add kCount resources, holding onto resources at random so we have a mix of purgeable and
985ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // unpurgeable resources.
986ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
987ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
988ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
989ddf30e64fe474847b204d7062fad3341d245062cbsalomon
990ddf30e64fe474847b204d7062fad3341d245062cbsalomon            TestResource* r = SkNEW_ARGS(TestResource, (context->getGpu()));
991ddf30e64fe474847b204d7062fad3341d245062cbsalomon            r->resourcePriv().setUniqueKey(key);
992ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (random.nextU() % kLockedFreq) {
993ddf30e64fe474847b204d7062fad3341d245062cbsalomon                // Make this is purgeable.
994ddf30e64fe474847b204d7062fad3341d245062cbsalomon                r->unref();
995ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++purgeableCnt;
996ddf30e64fe474847b204d7062fad3341d245062cbsalomon                if (purgeableCnt <= kNumToPurge) {
997ddf30e64fe474847b204d7062fad3341d245062cbsalomon                    *shouldPurgeIdxs.append() = j;
998ddf30e64fe474847b204d7062fad3341d245062cbsalomon                }
999ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
1000ddf30e64fe474847b204d7062fad3341d245062cbsalomon                *resourcesToUnref.append() = r;
1001ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1002ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1003ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1004ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Verify that the correct resources were purged.
1005ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int currShouldPurgeIdx = 0;
1006ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1007ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1008ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1009ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrGpuResource* res = cache->findAndRefUniqueResource(key);
1010ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (currShouldPurgeIdx < shouldPurgeIdxs.count() &&
1011ddf30e64fe474847b204d7062fad3341d245062cbsalomon                shouldPurgeIdxs[currShouldPurgeIdx] == j) {
1012ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++currShouldPurgeIdx;
1013ddf30e64fe474847b204d7062fad3341d245062cbsalomon                REPORTER_ASSERT(reporter, NULL == res);
1014ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
1015ddf30e64fe474847b204d7062fad3341d245062cbsalomon                REPORTER_ASSERT(reporter, NULL != res);
1016ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1017ddf30e64fe474847b204d7062fad3341d245062cbsalomon            SkSafeUnref(res);
1018ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1019ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1020ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < resourcesToUnref.count(); ++j) {
1021ddf30e64fe474847b204d7062fad3341d245062cbsalomon            resourcesToUnref[j]->unref();
1022ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1023ddf30e64fe474847b204d7062fad3341d245062cbsalomon    }
1024ddf30e64fe474847b204d7062fad3341d245062cbsalomon}
1025ddf30e64fe474847b204d7062fad3341d245062cbsalomon
102610e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_large_resource_count(skiatest::Reporter* reporter) {
102710e23caea3106be125acea10a637789e5a15c728bsalomon    // Set the cache size to double the resource count because we're going to create 2x that number
102810e23caea3106be125acea10a637789e5a15c728bsalomon    // resources, using two different key domains. Add a little slop to the bytes because we resize
102910e23caea3106be125acea10a637789e5a15c728bsalomon    // down to 1 byte after creating the resource.
1030c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    static const int kResourceCnt = 2000;
103110e23caea3106be125acea10a637789e5a15c728bsalomon
1032c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
1033c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
10340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
103510e23caea3106be125acea10a637789e5a15c728bsalomon
103610e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
10378718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
10388718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
10398718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
104024db3b1c35fb935660229da164fc5ad31977387fbsalomon
104110e23caea3106be125acea10a637789e5a15c728bsalomon        TestResource* resource;
104210e23caea3106be125acea10a637789e5a15c728bsalomon
104310e23caea3106be125acea10a637789e5a15c728bsalomon        resource = SkNEW_ARGS(TestResource, (context->getGpu()));
10448718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key1);
104510e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
104610e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
104710e23caea3106be125acea10a637789e5a15c728bsalomon
104810e23caea3106be125acea10a637789e5a15c728bsalomon        resource = SkNEW_ARGS(TestResource, (context->getGpu()));
10498718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key2);
105010e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
105110e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
105210e23caea3106be125acea10a637789e5a15c728bsalomon    }
105310e23caea3106be125acea10a637789e5a15c728bsalomon
105410e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
10550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 2 * kResourceCnt);
10560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 2 * kResourceCnt);
10570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 2 * kResourceCnt);
10580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 2 * kResourceCnt);
105910e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
10608718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
10618718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
10628718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
106324db3b1c35fb935660229da164fc5ad31977387fbsalomon
10648718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
10658718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
106610e23caea3106be125acea10a637789e5a15c728bsalomon    }
106710e23caea3106be125acea10a637789e5a15c728bsalomon
10680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
106910e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
10700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 0);
10710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 0);
10720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 0);
10730ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 0);
107410e23caea3106be125acea10a637789e5a15c728bsalomon
107510e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
10768718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
10778718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
10788718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
107924db3b1c35fb935660229da164fc5ad31977387fbsalomon
10808718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
10818718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
108210e23caea3106be125acea10a637789e5a15c728bsalomon    }
108310e23caea3106be125acea10a637789e5a15c728bsalomon}
108410e23caea3106be125acea10a637789e5a15c728bsalomon
1085c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
10864ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(ResourceCache, reporter, factory) {
1087c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
1088c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
1089c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        if (!GrContextFactory::IsRenderingGLContext(glType)) {
1090c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org            continue;
1091c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        }
1092c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        GrContext* context = factory->get(glType);
1093fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon        if (NULL == context) {
1094fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon            continue;
1095fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon        }
1096f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon        GrSurfaceDesc desc;
1097c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        desc.fConfig = kSkia8888_GrPixelConfig;
1098f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon        desc.fFlags = kRenderTarget_GrSurfaceFlag;
1099c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        desc.fWidth = gWidth;
1100c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        desc.fHeight = gHeight;
110169f6f00fd975823e825c5aa0b1b8f4416e7c812breed        SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
1102afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context,
1103afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                                                   SkSurface::kNo_Budgeted, info));
1104fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon        test_cache(reporter, context, surface->getCanvas());
110502a44a488605112aa6683c9d919e13b188112ce1bsalomon        test_stencil_buffers(reporter, context);
1106820dd6c335411aad889c1d7e8a857642ecd87e30bsalomon    }
1107334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
11088b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // The below tests create their own mock contexts.
110971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_no_key(reporter);
111084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    test_budgeting(reporter);
11115236cf480daf82b2f36e42795abdbbc915533a59bsalomon    test_unbudgeted(reporter);
1112c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    test_unbudgeted_to_scratch(reporter);
11138718aafec239c93485e45bbe8fed19d9a8def079bsalomon    test_duplicate_unique_key(reporter);
11148b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_duplicate_scratch_key(reporter);
111510e23caea3106be125acea10a637789e5a15c728bsalomon    test_remove_scratch_key(reporter);
11161c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    test_scratch_key_consistency(reporter);
11178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_purge_invalidated(reporter);
111871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_cache_chained_purge(reporter);
11198b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_resource_size_changed(reporter);
1120ddf30e64fe474847b204d7062fad3341d245062cbsalomon    test_timestamp_wrap(reporter);
112110e23caea3106be125acea10a637789e5a15c728bsalomon    test_large_resource_count(reporter);
1122c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
1123c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
1124c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#endif
1125