ResourceCacheTest.cpp revision c6363ef7b4763b36a9a0d255bc775a973d2fc7a5
1c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org/*
2c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org * Copyright 2013 Google Inc.
3c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org *
4c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org * found in the LICENSE file.
6c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org */
7c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
83f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon// Include here to ensure SK_SUPPORT_GPU is set correctly before it is examined.
93f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon#include "SkTypes.h"
103f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#if SK_SUPPORT_GPU
124ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org
13bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "GrContext.h"
14c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#include "GrContextFactory.h"
15bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "GrGpu.h"
163582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourceCacheAccess.h"
173582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourcePriv.h"
186bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon#include "GrRenderTarget.h"
196bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon#include "GrRenderTargetPriv.h"
200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#include "GrResourceCache.h"
216dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon#include "GrTest.h"
22bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon#include "SkCanvas.h"
2371cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkGr.h"
2471cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkMessageBus.h"
2569f6f00fd975823e825c5aa0b1b8f4416e7c812breed#include "SkSurface.h"
264ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.org#include "Test.h"
27c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
28c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gWidth = 640;
29c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.orgstatic const int gHeight = 480;
30c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
31c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
32334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonstatic void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanvas* canvas) {
33c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
34c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
35c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap src;
36deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    src.allocN32Pixels(size.width(), size.height());
37c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    src.eraseColor(SK_ColorBLACK);
38c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t srcSize = src.getSize();
39c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
4095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    size_t initialCacheSize;
4196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    context->getResourceCacheUsage(nullptr, &initialCacheSize);
42c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
43c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    int oldMaxNum;
44c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t oldMaxBytes;
4595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);
4617f1ae63d57a3f3d3a0ae50e1b25b3f8b18fd328skia.committer@gmail.com
47c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // Set the cache limits so we can fit 10 "src" images and the
48c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    // max number of textures doesn't matter
49c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    size_t maxCacheSize = initialCacheSize + 10*srcSize;
5095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(1000, maxCacheSize);
51c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
52c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    SkBitmap readback;
53deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    readback.allocN32Pixels(size.width(), size.height());
54c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
55c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    for (int i = 0; i < 100; ++i) {
56c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        canvas->drawBitmap(src, 0, 0);
57c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        canvas->readPixels(size, &readback);
58c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
59c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // "modify" the src texture
60c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        src.notifyPixelsChanged();
61c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
6295c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        size_t curCacheSize;
6396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        context->getResourceCacheUsage(nullptr, &curCacheSize);
64c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
65c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        // we should never go over the size limit
66c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
67c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    }
68c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
6995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
70c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
71c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
7202a44a488605112aa6683c9d919e13b188112ce1bsalomonstatic void test_stencil_buffers(skiatest::Reporter* reporter, GrContext* context) {
7302a44a488605112aa6683c9d919e13b188112ce1bsalomon    GrSurfaceDesc smallDesc;
7402a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fFlags = kRenderTarget_GrSurfaceFlag;
7502a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fConfig = kSkia8888_GrPixelConfig;
7602a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fWidth = 4;
7702a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fHeight = 4;
7802a44a488605112aa6683c9d919e13b188112ce1bsalomon    smallDesc.fSampleCnt = 0;
7902a44a488605112aa6683c9d919e13b188112ce1bsalomon
80d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    GrTextureProvider* cache = context->textureProvider();
81ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel    GrResourceProvider* resourceProvider = context->resourceProvider();
8202a44a488605112aa6683c9d919e13b188112ce1bsalomon    // Test that two budgeted RTs with the same desc share a stencil buffer.
83d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkAutoTUnref<GrTexture> smallRT0(cache->createTexture(smallDesc, true));
846bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (smallRT0 && smallRT0->asRenderTarget()) {
85ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel        resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget());
866bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
876bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
88d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkAutoTUnref<GrTexture> smallRT1(cache->createTexture(smallDesc, true));
896bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (smallRT1 && smallRT1->asRenderTarget()) {
90ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel        resourceProvider->attachStencilAttachment(smallRT1->asRenderTarget());
916bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
926bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon
938dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel    REPORTER_ASSERT(reporter,
948dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                    smallRT0 && smallRT1 &&
958dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                    smallRT0->asRenderTarget() && smallRT1->asRenderTarget() &&
96ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                    resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) ==
97ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                    resourceProvider->attachStencilAttachment(smallRT1->asRenderTarget()));
9802a44a488605112aa6683c9d919e13b188112ce1bsalomon
9902a44a488605112aa6683c9d919e13b188112ce1bsalomon    // An unbudgeted RT with the same desc should also share.
100d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkAutoTUnref<GrTexture> smallRT2(cache->createTexture(smallDesc, false));
1016bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (smallRT2 && smallRT2->asRenderTarget()) {
102ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel        resourceProvider->attachStencilAttachment(smallRT2->asRenderTarget());
1036bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
1048dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel    REPORTER_ASSERT(reporter,
1058dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                    smallRT0 && smallRT2 &&
1068dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                    smallRT0->asRenderTarget() && smallRT2->asRenderTarget() &&
107ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                    resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) ==
108ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                    resourceProvider->attachStencilAttachment(smallRT2->asRenderTarget()));
10902a44a488605112aa6683c9d919e13b188112ce1bsalomon
11002a44a488605112aa6683c9d919e13b188112ce1bsalomon    // An RT with a much larger size should not share.
11102a44a488605112aa6683c9d919e13b188112ce1bsalomon    GrSurfaceDesc bigDesc;
11202a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fFlags = kRenderTarget_GrSurfaceFlag;
11302a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fConfig = kSkia8888_GrPixelConfig;
11402a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fWidth = 400;
11502a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fHeight = 200;
11602a44a488605112aa6683c9d919e13b188112ce1bsalomon    bigDesc.fSampleCnt = 0;
117d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon    SkAutoTUnref<GrTexture> bigRT(cache->createTexture(bigDesc, false));
1186bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    if (bigRT && bigRT->asRenderTarget()) {
119ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel        resourceProvider->attachStencilAttachment(bigRT->asRenderTarget());
1206bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon    }
1218dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel    REPORTER_ASSERT(reporter,
1228dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                    smallRT0 && bigRT &&
1238dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                    smallRT0->asRenderTarget() && bigRT->asRenderTarget() &&
124ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                    resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) !=
125ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                    resourceProvider->attachStencilAttachment(bigRT->asRenderTarget()));
12602a44a488605112aa6683c9d919e13b188112ce1bsalomon
127762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon    if (context->caps()->maxSampleCount() >= 4) {
12802a44a488605112aa6683c9d919e13b188112ce1bsalomon        // An RT with a different sample count should not share.
12902a44a488605112aa6683c9d919e13b188112ce1bsalomon        GrSurfaceDesc smallMSAADesc = smallDesc;
13002a44a488605112aa6683c9d919e13b188112ce1bsalomon        smallMSAADesc.fSampleCnt = 4;
131d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        SkAutoTUnref<GrTexture> smallMSAART0(cache->createTexture(smallMSAADesc, false));
1326bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        if (smallMSAART0 && smallMSAART0->asRenderTarget()) {
133ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel            resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget());
1346bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        }
135b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#ifdef SK_BUILD_FOR_ANDROID
136b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        if (!smallMSAART0) {
137b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            // The nexus player seems to fail to create MSAA textures.
138b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon            return;
139b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon        }
140b602d4dff8a353f686ce6d7f9d01b7882cc10277bsalomon#endif
1416bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        REPORTER_ASSERT(reporter,
1426bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallRT0 && smallMSAART0 &&
1436bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallRT0->asRenderTarget() && smallMSAART0->asRenderTarget() &&
144ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                        resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) !=
145ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                        resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget()));
14602a44a488605112aa6683c9d919e13b188112ce1bsalomon        // A second MSAA RT should share with the first MSAA RT.
147d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon        SkAutoTUnref<GrTexture> smallMSAART1(cache->createTexture(smallMSAADesc, false));
1486bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
149ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel            resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget());
1506bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        }
1516bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon        REPORTER_ASSERT(reporter,
1526bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART0 && smallMSAART1 &&
1536bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART0->asRenderTarget() &&
1546bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon                        smallMSAART1->asRenderTarget() &&
155ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                        resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget()) ==
156ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                        resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget()));
15702a44a488605112aa6683c9d919e13b188112ce1bsalomon        // But not one with a larger sample count should not. (Also check that the request for 4
15802a44a488605112aa6683c9d919e13b188112ce1bsalomon        // samples didn't get rounded up to >= 8 or else they could share.).
159762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon        if (context->caps()->maxSampleCount() >= 8 &&
160762286309545c8a1e4bbc05dcd1fe3085d2a1f47bsalomon            smallMSAART0 && smallMSAART0->asRenderTarget() &&
161dded69693dd3779f081326cde24c3954505b129dvbuzinov            smallMSAART0->asRenderTarget()->numColorSamples() < 8) {
16202a44a488605112aa6683c9d919e13b188112ce1bsalomon            smallMSAADesc.fSampleCnt = 8;
163d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            smallMSAART1.reset(cache->createTexture(smallMSAADesc, false));
164d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon            SkAutoTUnref<GrTexture> smallMSAART1(cache->createTexture(smallMSAADesc, false));
1656bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            if (smallMSAART1 && smallMSAART1->asRenderTarget()) {
166ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget());
1676bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            }
1686bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon            REPORTER_ASSERT(reporter,
1698dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                        smallMSAART0 && smallMSAART1 &&
1708dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                        smallMSAART0->asRenderTarget() &&
1718dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel                        smallMSAART1->asRenderTarget() &&
172ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                        resourceProvider->attachStencilAttachment(smallMSAART0->asRenderTarget()) !=
173ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel                        resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget()));
17402a44a488605112aa6683c9d919e13b188112ce1bsalomon        }
17502a44a488605112aa6683c9d919e13b188112ce1bsalomon    }
17602a44a488605112aa6683c9d919e13b188112ce1bsalomon}
17702a44a488605112aa6683c9d919e13b188112ce1bsalomon
1786dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomonstatic void test_wrapped_resources(skiatest::Reporter* reporter, GrContext* context) {
179672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth    const GrGpu* gpu = context->getGpu();
180eeb8d99b4e58eb95cad3f7cd5438b9c2b3db7141jvanverth    // this test is only valid for GL
181eeb8d99b4e58eb95cad3f7cd5438b9c2b3db7141jvanverth    if (!gpu || !gpu->glContextForTesting()) {
1826dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
1836dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
1846dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
185672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth    GrBackendObject texIDs[2];
1866dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kW = 100;
1876dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    static const int kH = 100;
188672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
18996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    texIDs[0] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig);
19096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    texIDs[1] = gpu->createTestingOnlyBackendTexture(nullptr, kW, kH, kRGBA_8888_GrPixelConfig);
191672bb7fc6640e3fc68107354ed4ae45a2a1e2d29jvanverth
1926dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
1936dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
1946dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    GrBackendTextureDesc desc;
1956dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    desc.fConfig = kBGRA_8888_GrPixelConfig;
1966dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    desc.fWidth = kW;
1976dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    desc.fHeight = kH;
1986dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
1996dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    desc.fTextureHandle = texIDs[0];
2006dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    SkAutoTUnref<GrTexture> borrowed(context->textureProvider()->wrapBackendTexture(
2013e5f55542cbd23f1ad448cac3d29e8551204552cjvanverth                                     desc, kBorrow_GrWrapOwnership));
2026dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2036dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    desc.fTextureHandle = texIDs[1];
2046dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    SkAutoTUnref<GrTexture> adopted(context->textureProvider()->wrapBackendTexture(
2053e5f55542cbd23f1ad448cac3d29e8551204552cjvanverth                                    desc, kAdopt_GrWrapOwnership));
2066dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2076dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, SkToBool(borrowed) && SkToBool(adopted));
2086dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    if (!SkToBool(borrowed) || !SkToBool(adopted)) {
2096dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        return;
2106dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    }
2116dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
21296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    borrowed.reset(nullptr);
21396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    adopted.reset(nullptr);
2146dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2156dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->flush();
2166dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
217889579287770ba35156a73aa02d9ef5d2313c490jvanverth    bool borrowedIsAlive = gpu->isTestingOnlyBackendTexture(texIDs[0]);
218889579287770ba35156a73aa02d9ef5d2313c490jvanverth    bool adoptedIsAlive = gpu->isTestingOnlyBackendTexture(texIDs[1]);
2196dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2206dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, borrowedIsAlive);
2216dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    REPORTER_ASSERT(reporter, !adoptedIsAlive);
2226dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
223889579287770ba35156a73aa02d9ef5d2313c490jvanverth    gpu->deleteTestingOnlyBackendTexture(texIDs[0]);
2246dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2256dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon    context->resetContext();
2266dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon}
2276dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon
2286d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomonclass TestResource : public GrGpuResource {
2291c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    enum ScratchConstructor { kScratchConstructor };
230c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgpublic:
2316e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    static const size_t kDefaultSize = 100;
2322766c00fc0b6a07d46e5f74cdad45da2ef625237mtklein
2331c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    /** Property that distinctly categorizes the resource.
2341c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon     * For example, textures have width, height, ... */
23523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
2361c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2375236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
2385236cf480daf82b2f36e42795abdbbc915533a59bsalomon        : INHERITED(gpu, lifeCycle)
23996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
2401c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(size)
24123e619cf462b2a8a500f3ca750e099f79601f508bsalomon        , fProperty(kA_SimulatedProperty) {
2425236cf480daf82b2f36e42795abdbbc915533a59bsalomon        ++fNumAlive;
2435236cf480daf82b2f36e42795abdbbc915533a59bsalomon        this->registerWithCache();
2445236cf480daf82b2f36e42795abdbbc915533a59bsalomon    }
2455236cf480daf82b2f36e42795abdbbc915533a59bsalomon
2465236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource(GrGpu* gpu, GrGpuResource::LifeCycle lifeCycle)
2475236cf480daf82b2f36e42795abdbbc915533a59bsalomon        : INHERITED(gpu, lifeCycle)
24896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
2491c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
25023e619cf462b2a8a500f3ca750e099f79601f508bsalomon        , fProperty(kA_SimulatedProperty) {
251dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon        ++fNumAlive;
252dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon        this->registerWithCache();
253dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    }
254dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
2558b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    TestResource(GrGpu* gpu)
2565236cf480daf82b2f36e42795abdbbc915533a59bsalomon        : INHERITED(gpu, kCached_LifeCycle)
25796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
2581c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
25923e619cf462b2a8a500f3ca750e099f79601f508bsalomon        , fProperty(kA_SimulatedProperty) {
2608b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        ++fNumAlive;
2618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        this->registerWithCache();
2628b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
2638b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
26423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    static TestResource* CreateScratch(GrGpu* gpu, SimulatedProperty property, bool cached = true) {
265385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new TestResource(gpu, property, cached, kScratchConstructor);
266c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
267c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
268c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    ~TestResource() {
269334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon        --fNumAlive;
27071cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkSafeUnref(fToDelete);
271c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
272c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
27311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    void setSize(size_t size) {
27411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        fSize = size;
27511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        this->didChangeGpuMemorySize();
27611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
27711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
278334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int NumAlive() { return fNumAlive; }
279c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
28071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    void setUnrefWhenDestroyed(TestResource* resource) {
28171cb0c241e439b6ed746b90294d0b6916644a644bsalomon        SkRefCnt_SafeAssign(fToDelete, resource);
282c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    }
283c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
2841c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static void ComputeScratchKey(SimulatedProperty property, GrScratchKey* key) {
2851c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        static GrScratchKey::ResourceType t = GrScratchKey::GenerateResourceType();
2861c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey::Builder builder(key, t, kScratchKeyFieldCnt);
28724db3b1c35fb935660229da164fc5ad31977387fbsalomon        for (int i = 0; i < kScratchKeyFieldCnt; ++i) {
28824db3b1c35fb935660229da164fc5ad31977387fbsalomon            builder[i] = static_cast<uint32_t>(i + property);
2891c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        }
2901c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
2911c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
2921c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    static size_t ExpectedScratchKeySize() {
2931c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
2941c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
2951c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
296c665804300096c2e7617379835bb83d715538788commit-bot@chromium.orgprivate:
29724db3b1c35fb935660229da164fc5ad31977387fbsalomon    static const int kScratchKeyFieldCnt = 6;
2981c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
299c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource(GrGpu* gpu, SimulatedProperty property, bool cached, ScratchConstructor)
300c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        : INHERITED(gpu, cached ? kCached_LifeCycle : kUncached_LifeCycle)
30196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        , fToDelete(nullptr)
3021c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fSize(kDefaultSize)
3031c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        , fProperty(property) {
3041c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        GrScratchKey scratchKey;
3051c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ComputeScratchKey(fProperty, &scratchKey);
3061c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        this->setScratchKey(scratchKey);
3071c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        ++fNumAlive;
3081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon        this->registerWithCache();
3091c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    }
3101c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
31136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t onGpuMemorySize() const override { return fSize; }
31269ed47f42d4877c178fdc0031cb01af2966ae235bsalomon
313c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    TestResource* fToDelete;
31411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    size_t fSize;
315334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    static int fNumAlive;
3161c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    SimulatedProperty fProperty;
3176d3fe022d68fd6dd32c0fab30e24fa5a4f048946bsalomon    typedef GrGpuResource INHERITED;
318c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org};
319334355742137cc238887d4f85856e6c4d9ec8aa8bsalomonint TestResource::fNumAlive = 0;
320c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
321c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonclass Mock {
322c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonpublic:
323c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock(int maxCnt, size_t maxBytes) {
324c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext.reset(GrContext::CreateMockContext());
325c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        SkASSERT(fContext);
326c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        fContext->setResourceCacheLimits(maxCnt, maxBytes);
3270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = fContext->getResourceCache();
3280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        cache->purgeAllUnlocked();
3290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        SkASSERT(0 == cache->getResourceCount() && 0 == cache->getResourceBytes());
33071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    }
331c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
3320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache() { return fContext->getResourceCache(); }
333c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
334c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context() { return fContext; }
335c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
336c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonprivate:
337c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    SkAutoTUnref<GrContext> fContext;
338c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon};
339c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
340c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_no_key(skiatest::Reporter* reporter) {
341c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
342c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
3430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
34471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
34571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Create a bunch of resources with no keys
346385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
347385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
348385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* c = new TestResource(context->getGpu());
349385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* d = new TestResource(context->getGpu());
35071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->setSize(11);
35171cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->setSize(12);
35271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->setSize(13);
35371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->setSize(14);
35471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
35571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
3560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
35771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() +
3580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              d->gpuMemorySize() == cache->getResourceBytes());
35971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
36071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    // Should be safe to purge without deleting the resources since we still have refs.
3610ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
36271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive());
36371cb0c241e439b6ed746b90294d0b6916644a644bsalomon
3648718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Since the resources have neither unique nor scratch keys, delete immediately upon unref.
36571cb0c241e439b6ed746b90294d0b6916644a644bsalomon
36671cb0c241e439b6ed746b90294d0b6916644a644bsalomon    a->unref();
36771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
3680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
36971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() + d->gpuMemorySize() ==
3700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
37171cb0c241e439b6ed746b90294d0b6916644a644bsalomon
37271cb0c241e439b6ed746b90294d0b6916644a644bsalomon    c->unref();
37371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
3740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
37571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() ==
3760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
37771cb0c241e439b6ed746b90294d0b6916644a644bsalomon
37871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    d->unref();
37971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
3800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
3810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
38271cb0c241e439b6ed746b90294d0b6916644a644bsalomon
38371cb0c241e439b6ed746b90294d0b6916644a644bsalomon    b->unref();
38471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
3850ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
3860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
38771cb0c241e439b6ed746b90294d0b6916644a644bsalomon}
38871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
38924db3b1c35fb935660229da164fc5ad31977387fbsalomon// Each integer passed as a template param creates a new domain.
3908718aafec239c93485e45bbe8fed19d9a8def079bsalomontemplate <int> static void make_unique_key(GrUniqueKey* key, int data) {
3918718aafec239c93485e45bbe8fed19d9a8def079bsalomon    static GrUniqueKey::Domain d = GrUniqueKey::GenerateDomain();
3928718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey::Builder builder(key, d, 1);
39324db3b1c35fb935660229da164fc5ad31977387fbsalomon    builder[0] = data;
39424db3b1c35fb935660229da164fc5ad31977387fbsalomon}
39524db3b1c35fb935660229da164fc5ad31977387fbsalomon
39684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomonstatic void test_budgeting(skiatest::Reporter* reporter) {
397c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
398c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
3990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
400dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4018718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
4028718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
403dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4048718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create a scratch, a unique, and a wrapped resource
4051c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    TestResource* scratch =
40623e619cf462b2a8a500f3ca750e099f79601f508bsalomon            TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
407dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(10);
408385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* unique = new TestResource(context->getGpu());
4098718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
410f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
411385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* wrapped = new TestResource(context->getGpu(), GrGpuResource::kBorrowed_LifeCycle);
4125236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->setSize(12);
413385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* unbudgeted =
414385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            new TestResource(context->getGpu(), GrGpuResource::kUncached_LifeCycle);
41584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->setSize(13);
416dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4178718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Make sure we can't add a unique key to the wrapped resource
4188718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey2;
4198718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey2, 1);
420f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    wrapped->resourcePriv().setUniqueKey(uniqueKey2);
42196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == cache->findAndRefUniqueResource(uniqueKey2));
422dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
423dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Make sure sizes are as we expect
4240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
4258718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
42684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
4270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4298718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
4300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
431dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
43263c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
4330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 4 == cache->getResourceCount());
4358718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
43684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon                              wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() ==
4370ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
4398718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() ==
4400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getBudgetedResourceBytes());
441dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
442dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    // Unreffing the wrapped resource should free it right away.
443dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
4440ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
4458718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() +
4460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
447dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
44884c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    // Now try freeing the budgeted resources first
449385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    wrapped = new TestResource(context->getGpu(), GrGpuResource::kBorrowed_LifeCycle);
450dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->setSize(12);
4518718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
4520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
45484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() +
4550ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              unbudgeted->gpuMemorySize() == cache->getResourceBytes());
4560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
4570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes());
458dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
459dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    scratch->unref();
4600ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
4610ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
46284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() ==
4630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
4640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
466dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
467dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon    wrapped->unref();
4680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes());
4700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
47284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon
47384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    unbudgeted->unref();
4740ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
4750ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
4760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
4770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
478dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon}
479dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon
4805236cf480daf82b2f36e42795abdbbc915533a59bsalomonstatic void test_unbudgeted(skiatest::Reporter* reporter) {
481c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 30000);
482c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
4830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
4845236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4858718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey uniqueKey;
4868718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&uniqueKey, 0);
4875236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4885236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* scratch;
4898718aafec239c93485e45bbe8fed19d9a8def079bsalomon    TestResource* unique;
4905236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* wrapped;
4915236cf480daf82b2f36e42795abdbbc915533a59bsalomon    TestResource* unbudgeted;
4925236cf480daf82b2f36e42795abdbbc915533a59bsalomon
4935236cf480daf82b2f36e42795abdbbc915533a59bsalomon    // A large uncached or wrapped resource shouldn't evict anything.
49423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    scratch = TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
4955236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->setSize(10);
4965236cf480daf82b2f36e42795abdbbc915533a59bsalomon    scratch->unref();
4970ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
4980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes());
4990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes());
5015236cf480daf82b2f36e42795abdbbc915533a59bsalomon
502385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    unique = new TestResource(context->getGpu());
5038718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->setSize(11);
504f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    unique->resourcePriv().setUniqueKey(uniqueKey);
5058718aafec239c93485e45bbe8fed19d9a8def079bsalomon    unique->unref();
5060ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5090ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
5105236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    size_t large = 2 * cache->getResourceBytes();
512385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    unbudgeted = new TestResource(context->getGpu(), large, GrGpuResource::kUncached_LifeCycle);
5130ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5140ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
5150ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
5175236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5185236cf480daf82b2f36e42795abdbbc915533a59bsalomon    unbudgeted->unref();
5190ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5200ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5210ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5220ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
5235236cf480daf82b2f36e42795abdbbc915533a59bsalomon
524385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    wrapped = new TestResource(context->getGpu(), large, GrGpuResource::kBorrowed_LifeCycle);
5250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
5260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
5270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
5295236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5305236cf480daf82b2f36e42795abdbbc915533a59bsalomon    wrapped->unref();
5310ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
5320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes());
5330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
5340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
5350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon
5360ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
5370ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5380ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5390ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
5415236cf480daf82b2f36e42795abdbbc915533a59bsalomon}
5425236cf480daf82b2f36e42795abdbbc915533a59bsalomon
5433582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon// This method can't be static because it needs to friended in GrGpuResource::CacheAccess.
5443582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomonvoid test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
5453582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon/*static*/ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter) {
546c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(10, 300);
547c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
5480ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
549c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
550c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    TestResource* resource =
55123e619cf462b2a8a500f3ca750e099f79601f508bsalomon        TestResource::CreateScratch(context->getGpu(), TestResource::kA_SimulatedProperty, false);
552c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrScratchKey key;
55323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
554c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
555c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    size_t size = resource->gpuMemorySize();
556c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    for (int i = 0; i < 2; ++i) {
557c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Since this resource is unbudgeted, it should not be reachable as scratch.
5583582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
559c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
5603582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, !resource->resourcePriv().isBudgeted());
56196fcdcc219d2a0d3579719b84b28bede76efba64halcanary        REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
5620ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
5640ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5650ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
566c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
567c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        // Once it is unrefed, it should become available as scratch.
568c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        resource->unref();
5690ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
5710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
5736e83ac778f8f90939abe3aee3ea865428dff592frobertphillips        resource = static_cast<TestResource*>(cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0));
574c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource);
5753582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key);
576c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        REPORTER_ASSERT(reporter, resource->cacheAccess().isScratch());
5773582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon        REPORTER_ASSERT(reporter, resource->resourcePriv().isBudgeted());
578c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
579c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        if (0 == i) {
580c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // If made unbudgeted, it should return to original state: ref'ed and unbudgeted. Try
581c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // the above tests again.
5823582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().makeUnbudgeted();
583c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        } else {
584c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // After the second time around, try removing the scratch key
5853582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            resource->resourcePriv().removeScratchKey();
5860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
5870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getResourceBytes());
5880ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount());
5890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes());
5903582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid());
591c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch());
5923582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon            REPORTER_ASSERT(reporter, resource->resourcePriv().isBudgeted());
593c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
594c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            // now when it is unrefed it should die since it has no key.
595c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon            resource->unref();
5960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
5970ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
5980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount());
5990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon            REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes());
600c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        }
6018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    }
602c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon}
603c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon
604c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomonstatic void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
605c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
606c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
6070ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
6088b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
6098b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Create two resources that have the same scratch key.
61023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
61123e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
61223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
61323e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
6148b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
6158b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->setSize(12);
6161c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
61723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
6181c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Check for negative case consistency. (leaks upon test failure.)
61996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, nullptr == cache->findAndRefScratchResource(scratchKey1, TestResource::kDefaultSize, 0));
6201c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6211c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
62223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
6231c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
625ac49acda520292b059bc37fd368dff912626c3d9bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
62871cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() ==
6290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon                              cache->getResourceBytes());
6308b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
63163c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Our refs mean that the resources are non purgeable.
6320ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6338b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
6358b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
6368b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Unref but don't purge
6378b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->unref();
6388b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
6398b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6418b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
64263c992f6c05ea728b5386de61d279f10eb7e08d9bsalomon    // Purge again. This time resources should be purgeable.
6430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
6448b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
6450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
6460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
6478b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
6488b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
64910e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_remove_scratch_key(skiatest::Reporter* reporter) {
650c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
651c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
6520ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
65310e23caea3106be125acea10a637789e5a15c728bsalomon
65410e23caea3106be125acea10a637789e5a15c728bsalomon    // Create two resources that have the same scratch key.
65523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
65623e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
65723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
65823e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
65910e23caea3106be125acea10a637789e5a15c728bsalomon    a->unref();
66010e23caea3106be125acea10a637789e5a15c728bsalomon    b->unref();
66110e23caea3106be125acea10a637789e5a15c728bsalomon
6621c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
6631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
66423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
6651c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
66696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
6671c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
6680ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    // Scratch resources are registered with GrResourceCache just by existing. There are 2.
66923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
67010e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 2 == cache->countScratchEntriesForKey(scratchKey));)
6720ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
67310e23caea3106be125acea10a637789e5a15c728bsalomon
67410e23caea3106be125acea10a637789e5a15c728bsalomon    // Find the first resource and remove its scratch key
67510e23caea3106be125acea10a637789e5a15c728bsalomon    GrGpuResource* find;
6766e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
6773582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
67810e23caea3106be125acea10a637789e5a15c728bsalomon    // It's still alive, but not cached by scratch key anymore
67910e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
6800ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
6810ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
68210e23caea3106be125acea10a637789e5a15c728bsalomon
68310e23caea3106be125acea10a637789e5a15c728bsalomon    // The cache should immediately delete it when it's unrefed since it isn't accessible.
68410e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
68510e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
6860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 1 == cache->countScratchEntriesForKey(scratchKey));)
6870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
68810e23caea3106be125acea10a637789e5a15c728bsalomon
68910e23caea3106be125acea10a637789e5a15c728bsalomon    // Repeat for the second resource.
6906e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
6913582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
69210e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
6930ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
6940ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
69510e23caea3106be125acea10a637789e5a15c728bsalomon
69610e23caea3106be125acea10a637789e5a15c728bsalomon    // Should be able to call this multiple times with no problem.
6973582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon    find->resourcePriv().removeScratchKey();
69810e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
6990ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
70110e23caea3106be125acea10a637789e5a15c728bsalomon
70210e23caea3106be125acea10a637789e5a15c728bsalomon    find->unref();
70310e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
7040ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    SkDEBUGCODE(REPORTER_ASSERT(reporter, 0 == cache->countScratchEntriesForKey(scratchKey));)
7050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
70610e23caea3106be125acea10a637789e5a15c728bsalomon}
70710e23caea3106be125acea10a637789e5a15c728bsalomon
7081c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomonstatic void test_scratch_key_consistency(skiatest::Reporter* reporter) {
709c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
710c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
7121c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7131c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Create two resources that have the same scratch key.
71423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* a = TestResource::CreateScratch(context->getGpu(),
71523e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
71623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* b = TestResource::CreateScratch(context->getGpu(),
71723e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kB_SimulatedProperty);
7181c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    a->unref();
7191c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    b->unref();
7201c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7211c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey;
7221c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key comparison and assignment is consistent.
7231c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey1;
72423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey1);
7251c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    GrScratchKey scratchKey2;
72623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey2);
7271c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1.size() == TestResource::ExpectedScratchKeySize());
7281c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey2);
7291c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey1);
7301c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey1;
7311c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
7321c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 == scratchKey);
7331c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey1);
7341c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 != scratchKey);
7351c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey2);
7361c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey = scratchKey2;
7371c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey.size() == TestResource::ExpectedScratchKeySize());
7381c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey1 != scratchKey);
7391c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey != scratchKey1);
7401c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey2 == scratchKey);
7411c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, scratchKey == scratchKey2);
7421c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7431c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Ensure that scratch key lookup is correct for negative case.
74423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
7451c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // (following leaks upon test failure).
74696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0) == nullptr);
7471c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7481c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    // Find the first resource with a scratch key and a copy of a scratch key.
74923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kB_SimulatedProperty, &scratchKey);
7506e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
75196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
7521c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
7531c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7541c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    scratchKey2 = scratchKey;
7556e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    find = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
75696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find != nullptr);
7571c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find == a || find == b);
7581c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7596e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* find2 = cache->findAndRefScratchResource(scratchKey2, TestResource::kDefaultSize, 0);
76096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    REPORTER_ASSERT(reporter, find2 != nullptr);
7611c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 == a || find2 == b);
7621c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    REPORTER_ASSERT(reporter, find2 != find);
7631c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find2->unref();
7641c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    find->unref();
7651c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon}
7661c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon
7678718aafec239c93485e45bbe8fed19d9a8def079bsalomonstatic void test_duplicate_unique_key(skiatest::Reporter* reporter) {
768c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
769c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
7700ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
7718b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
7728718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key;
7738718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key, 0);
774334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
7758718aafec239c93485e45bbe8fed19d9a8def079bsalomon    // Create two resources that we will attempt to register with the same unique key.
776385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
7778b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    a->setSize(11);
77871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
779f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Set key on resource a.
780f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
781f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
782f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
783f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
784f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Make sure that redundantly setting a's key works.
785f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->resourcePriv().setUniqueKey(key);
786f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a == cache->findAndRefUniqueResource(key));
787f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
788f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
789f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() == cache->getResourceBytes());
790f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
791f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
792f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Create resource b and set the same key. It should replace a's unique key cache entry.
793385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
794f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->setSize(12);
795f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->resourcePriv().setUniqueKey(key);
796f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b == cache->findAndRefUniqueResource(key));
797f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    b->unref();
79871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
799f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Still have two resources because a is still reffed.
8000ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
801f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() == cache->getResourceBytes());
8028b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
8038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
804f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    a->unref();
805f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now a should be gone.
806f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
807f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() == cache->getResourceBytes());
808f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
809f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon
810f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Now replace b with c, but make sure c can start with one unique key and change it to b's key.
811f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Also make b be unreffed when replacement occurs.
8128b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    b->unref();
813385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* c = new TestResource(context->getGpu());
814f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    GrUniqueKey differentKey;
815f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    make_unique_key<0>(&differentKey, 1);
816f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->setSize(13);
817f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(differentKey);
818f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
819f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, b->gpuMemorySize() + c->gpuMemorySize() == cache->getResourceBytes());
820f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
821f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c replaces b and b should be immediately purged.
822f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().setUniqueKey(key);
8230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
824f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
82571cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
82671cb0c241e439b6ed746b90294d0b6916644a644bsalomon
827f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // c shouldn't be purged because it is ref'ed.
8280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
8290ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
830f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
8318b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
8328b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
833f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Drop the ref on c, it should be kept alive because it has a unique key.
834f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
8350ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
836f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c->gpuMemorySize() == cache->getResourceBytes());
83771cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
83871cb0c241e439b6ed746b90294d0b6916644a644bsalomon
839f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    // Verify that we can find c, then remove its unique key. It should get purged immediately.
840f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    REPORTER_ASSERT(reporter, c == cache->findAndRefUniqueResource(key));
841f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->resourcePriv().removeUniqueKey();
842f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon    c->unref();
8430ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
8440ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
8458b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
84684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
84784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    {
84884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        GrUniqueKey key2;
84984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        make_unique_key<0>(&key2, 0);
850385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        SkAutoTUnref<TestResource> d(new TestResource(context->getGpu()));
85184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        int foo = 4132;
85284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        SkAutoTUnref<SkData> data(SkData::NewWithCopy(&foo, sizeof(foo)));
85384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        key2.setCustomData(data.get());
85484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco        d->resourcePriv().setUniqueKey(key2);
85584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    }
85684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
85784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3;
85884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key3, 0);
85984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    SkAutoTUnref<GrGpuResource> d2(cache->findAndRefUniqueResource(key3));
86084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) d2->getUniqueKey().getCustomData()->data() == 4132);
8618b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon}
8628b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8638b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_purge_invalidated(skiatest::Reporter* reporter) {
864c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(5, 30000);
865c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
8660ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
8678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
8688718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2, key3;
8698718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
8708718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
8718718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key3, 3);
8728b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
87323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Add three resources to the cache. Only c is usable as scratch.
874385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
875385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
87623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource* c = TestResource::CreateScratch(context->getGpu(),
87723e619cf462b2a8a500f3ca750e099f79601f508bsalomon                                                  TestResource::kA_SimulatedProperty);
8788718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
8798718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
8808718aafec239c93485e45bbe8fed19d9a8def079bsalomon    c->resourcePriv().setUniqueKey(key3);
881c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org    a->unref();
88223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // hold b until *after* the message is sent.
8838b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    c->unref();
884c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
8858718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
8868718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
8878718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
888334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon    REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
88923e619cf462b2a8a500f3ca750e099f79601f508bsalomon
8908718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef GrUniqueKeyInvalidatedMessage Msg;
8918718aafec239c93485e45bbe8fed19d9a8def079bsalomon    typedef SkMessageBus<GrUniqueKeyInvalidatedMessage> Bus;
89223e619cf462b2a8a500f3ca750e099f79601f508bsalomon
89323e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Invalidate two of the three, they should be purged and no longer accessible via their keys.
89423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key1));
89523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key2));
8960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
89723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // a should be deleted now, but we still have a ref on b.
8988718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
8998718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
90023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9018718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, cache->hasUniqueKey(key3));
9028b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // Invalidate the third.
90423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    Bus::Post(Msg(key3));
9050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAsNeeded();
90623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // we still have a ref on b, c should be recycled as scratch.
90723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9088718aafec239c93485e45bbe8fed19d9a8def079bsalomon    REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key3));
90971cb0c241e439b6ed746b90294d0b6916644a644bsalomon
91023e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // make b purgeable. It should be immediately deleted since it has no key.
91123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    b->unref();
91223e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, 1 == TestResource::NumAlive());
91323e619cf462b2a8a500f3ca750e099f79601f508bsalomon
91423e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Make sure we actually get to c via it's scratch key, before we say goodbye.
91523e619cf462b2a8a500f3ca750e099f79601f508bsalomon    GrScratchKey scratchKey;
91623e619cf462b2a8a500f3ca750e099f79601f508bsalomon    TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &scratchKey);
9176e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    GrGpuResource* scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
91823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, scratch == c);
91923e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
92023e619cf462b2a8a500f3ca750e099f79601f508bsalomon
92123e619cf462b2a8a500f3ca750e099f79601f508bsalomon    // Get rid of c.
9220ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
9236e83ac778f8f90939abe3aee3ea865428dff592frobertphillips    scratch = cache->findAndRefScratchResource(scratchKey, TestResource::kDefaultSize, 0);
92471cb0c241e439b6ed746b90294d0b6916644a644bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
9250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
9260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
92723e619cf462b2a8a500f3ca750e099f79601f508bsalomon    REPORTER_ASSERT(reporter, !scratch);
92823e619cf462b2a8a500f3ca750e099f79601f508bsalomon    SkSafeUnref(scratch);
929c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org}
930c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org
93171cb0c241e439b6ed746b90294d0b6916644a644bsalomonstatic void test_cache_chained_purge(skiatest::Reporter* reporter) {
932c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(3, 30000);
933c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
9340ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
9358b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9368718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
9378718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
9388718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
939bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
940385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* a = new TestResource(context->getGpu());
941385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    TestResource* b = new TestResource(context->getGpu());
9428718aafec239c93485e45bbe8fed19d9a8def079bsalomon    a->resourcePriv().setUniqueKey(key1);
9438718aafec239c93485e45bbe8fed19d9a8def079bsalomon    b->resourcePriv().setUniqueKey(key2);
94471cb0c241e439b6ed746b90294d0b6916644a644bsalomon
945c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Make a cycle
946c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->setUnrefWhenDestroyed(b);
947c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->setUnrefWhenDestroyed(a);
948334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
949c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
950334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
951c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    a->unref();
952c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    b->unref();
9538b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
954c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
9558b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon
9560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
957c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
958f21dab95405979a4aff9f6a741c818304a67f220bsalomon
959c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    // Break the cycle
96096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    a->setUnrefWhenDestroyed(nullptr);
961c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
962ac49acda520292b059bc37fd368dff912626c3d9bsalomon
9630ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
964c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
965bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org}
966bd58febffb103ea830bf027c5a95313548f7ea8ecommit-bot@chromium.org
9678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomonstatic void test_resource_size_changed(skiatest::Reporter* reporter) {
9688718aafec239c93485e45bbe8fed19d9a8def079bsalomon    GrUniqueKey key1, key2;
9698718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key1, 1);
9708718aafec239c93485e45bbe8fed19d9a8def079bsalomon    make_unique_key<0>(&key2, 2);
97111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
97211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test changing resources sizes (both increase & decrease).
97311c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
974c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(3, 30000);
975c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
9760ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
97711c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
978385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* a = new TestResource(context->getGpu());
9798718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
98011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
98111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
982385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* b = new TestResource(context->getGpu());
9838718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
98411c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
98511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
9870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
9888b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
9898718aafec239c93485e45bbe8fed19d9a8def079bsalomon            SkAutoTUnref<TestResource> find2(
9908718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key2)));
9918b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(200);
9928718aafec239c93485e45bbe8fed19d9a8def079bsalomon            SkAutoTUnref<TestResource> find1(
9938718aafec239c93485e45bbe8fed19d9a8def079bsalomon                static_cast<TestResource*>(cache->findAndRefUniqueResource(key1)));
9948b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find1->setSize(50);
9958b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
99611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
9970ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 250 == cache->getResourceBytes());
9980ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
99911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
100011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
100111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    // Test increasing a resources size beyond the cache budget.
100211c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    {
1003c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        Mock mock(2, 300);
1004c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon        GrContext* context = mock.context();
10050ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        GrResourceCache* cache = mock.cache();
100611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1007385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* a = new TestResource(context->getGpu());
10088b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        a->setSize(100);
10098718aafec239c93485e45bbe8fed19d9a8def079bsalomon        a->resourcePriv().setUniqueKey(key1);
101011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        a->unref();
101111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1012385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        TestResource* b = new TestResource(context->getGpu());
10138b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        b->setSize(100);
10148718aafec239c93485e45bbe8fed19d9a8def079bsalomon        b->resourcePriv().setUniqueKey(key2);
101511c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org        b->unref();
101611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10170ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 200 == cache->getResourceBytes());
10180ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 2 == cache->getResourceCount());
101911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10208b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        {
10218718aafec239c93485e45bbe8fed19d9a8def079bsalomon            SkAutoTUnref<TestResource> find2(static_cast<TestResource*>(
10228718aafec239c93485e45bbe8fed19d9a8def079bsalomon                cache->findAndRefUniqueResource(key2)));
10238b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon            find2->setSize(201);
10248b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon        }
10258718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
102611c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
10270ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 201 == cache->getResourceBytes());
10280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon        REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
102911c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org    }
103011c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org}
103111c6b39cfa24f812ceb115589f51a60a56ef14fecommit-bot@chromium.org
1032ddf30e64fe474847b204d7062fad3341d245062cbsalomonstatic void test_timestamp_wrap(skiatest::Reporter* reporter) {
1033ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kCount = 50;
1034ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetCnt = kCount / 2;
1035ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kLockedFreq = 8;
1036ddf30e64fe474847b204d7062fad3341d245062cbsalomon    static const int kBudgetSize = 0x80000000;
1037ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1038ddf30e64fe474847b204d7062fad3341d245062cbsalomon    SkRandom random;
1039ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1040ddf30e64fe474847b204d7062fad3341d245062cbsalomon    // Run the test 2*kCount times;
1041ddf30e64fe474847b204d7062fad3341d245062cbsalomon    for (int i = 0; i < 2 * kCount; ++i ) {
1042ddf30e64fe474847b204d7062fad3341d245062cbsalomon        Mock mock(kBudgetCnt, kBudgetSize);
1043ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrContext* context = mock.context();
1044ddf30e64fe474847b204d7062fad3341d245062cbsalomon        GrResourceCache* cache = mock.cache();
1045ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1046ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Pick a random number of resources to add before the timestamp will wrap.
1047ddf30e64fe474847b204d7062fad3341d245062cbsalomon        cache->changeTimestamp(SK_MaxU32 - random.nextULessThan(kCount + 1));
1048ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1049ddf30e64fe474847b204d7062fad3341d245062cbsalomon        static const int kNumToPurge = kCount - kBudgetCnt;
1050ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1051ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<int> shouldPurgeIdxs;
1052ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int purgeableCnt = 0;
1053ddf30e64fe474847b204d7062fad3341d245062cbsalomon        SkTDArray<GrGpuResource*> resourcesToUnref;
1054ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1055ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Add kCount resources, holding onto resources at random so we have a mix of purgeable and
1056ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // unpurgeable resources.
1057ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1058ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1059ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1060ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1061385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
1062ddf30e64fe474847b204d7062fad3341d245062cbsalomon            r->resourcePriv().setUniqueKey(key);
1063ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (random.nextU() % kLockedFreq) {
1064ddf30e64fe474847b204d7062fad3341d245062cbsalomon                // Make this is purgeable.
1065ddf30e64fe474847b204d7062fad3341d245062cbsalomon                r->unref();
1066ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++purgeableCnt;
1067ddf30e64fe474847b204d7062fad3341d245062cbsalomon                if (purgeableCnt <= kNumToPurge) {
1068ddf30e64fe474847b204d7062fad3341d245062cbsalomon                    *shouldPurgeIdxs.append() = j;
1069ddf30e64fe474847b204d7062fad3341d245062cbsalomon                }
1070ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
1071ddf30e64fe474847b204d7062fad3341d245062cbsalomon                *resourcesToUnref.append() = r;
1072ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1073ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1074ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1075ddf30e64fe474847b204d7062fad3341d245062cbsalomon        // Verify that the correct resources were purged.
1076ddf30e64fe474847b204d7062fad3341d245062cbsalomon        int currShouldPurgeIdx = 0;
1077ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < kCount; ++j) {
1078ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrUniqueKey key;
1079ddf30e64fe474847b204d7062fad3341d245062cbsalomon            make_unique_key<0>(&key, j);
1080ddf30e64fe474847b204d7062fad3341d245062cbsalomon            GrGpuResource* res = cache->findAndRefUniqueResource(key);
1081ddf30e64fe474847b204d7062fad3341d245062cbsalomon            if (currShouldPurgeIdx < shouldPurgeIdxs.count() &&
1082ddf30e64fe474847b204d7062fad3341d245062cbsalomon                shouldPurgeIdxs[currShouldPurgeIdx] == j) {
1083ddf30e64fe474847b204d7062fad3341d245062cbsalomon                ++currShouldPurgeIdx;
108496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr == res);
1085ddf30e64fe474847b204d7062fad3341d245062cbsalomon            } else {
108696fcdcc219d2a0d3579719b84b28bede76efba64halcanary                REPORTER_ASSERT(reporter, nullptr != res);
1087ddf30e64fe474847b204d7062fad3341d245062cbsalomon            }
1088ddf30e64fe474847b204d7062fad3341d245062cbsalomon            SkSafeUnref(res);
1089ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1090ddf30e64fe474847b204d7062fad3341d245062cbsalomon
1091ddf30e64fe474847b204d7062fad3341d245062cbsalomon        for (int j = 0; j < resourcesToUnref.count(); ++j) {
1092ddf30e64fe474847b204d7062fad3341d245062cbsalomon            resourcesToUnref[j]->unref();
1093ddf30e64fe474847b204d7062fad3341d245062cbsalomon        }
1094ddf30e64fe474847b204d7062fad3341d245062cbsalomon    }
1095ddf30e64fe474847b204d7062fad3341d245062cbsalomon}
1096ddf30e64fe474847b204d7062fad3341d245062cbsalomon
10973f324321cdd8fde7976d958e2888a1ec4e657e35bsalomonstatic void test_flush(skiatest::Reporter* reporter) {
10983f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    Mock mock(1000000, 1000000);
10993f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrContext* context = mock.context();
11003f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    GrResourceCache* cache = mock.cache();
11013f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11023f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // The current cache impl will round the max flush count to the next power of 2. So we choose a
11033f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // power of two here to keep things simpler.
11043f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    static const int kFlushCount = 16;
11053f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    cache->setLimits(1000000, 1000000, kFlushCount);
11063f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11073f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
11083f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Insert a resource and send a flush notification kFlushCount times.
11093f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1110385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
11113f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
11123f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
11133f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
11143f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->unref();
11153f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            cache->notifyFlushOccurred();
11163f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11173f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11183f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Send flush notifications to the cache. Each flush should purge the oldest resource.
11193f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount - 1; ++i) {
11203f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // The first resource was purged after the last flush in the initial loop, hence the -1.
11213f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount - i - 1 == cache->getResourceCount());
11223f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            for (int j = 0; j < i; ++j) {
11233f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrUniqueKey k;
11243f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                make_unique_key<1>(&k, j);
11253f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                GrGpuResource* r = cache->findAndRefUniqueResource(k);
11263f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                REPORTER_ASSERT(reporter, !SkToBool(r));
11273f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                SkSafeUnref(r);
11283f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
11293f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            cache->notifyFlushOccurred();
11303f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11313f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11323f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
11333f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
11343f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
11353f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11363f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // Do a similar test but where we leave refs on some resources to prevent them from being
11373f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    // purged.
11383f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    {
11393f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        GrGpuResource* refedResources[kFlushCount >> 1];
11403f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
1141385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            TestResource* r = new TestResource(context->getGpu());
11423f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            GrUniqueKey k;
11433f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            make_unique_key<1>(&k, i);
11443f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            r->resourcePriv().setUniqueKey(k);
11453f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Leave a ref on every other resource, beginning with the first.
11463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            if (SkToBool(i & 0x1)) {
11473f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                refedResources[i/2] = r;
11483f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            } else {
11493f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon                r->unref();
11503f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            }
11513f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            cache->notifyFlushOccurred();
11523f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11533f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11543f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
11553f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            // Should get a resource purged every other flush.
11563f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount - i/2 - 1 == cache->getResourceCount());
11573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            cache->notifyFlushOccurred();
11583f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11593f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11603f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // Unref all the resources that we kept refs on in the first loop.
11613f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount >> 1; ++i) {
11623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            refedResources[i]->unref();
11633f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11643f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11653f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // When we unref'ed them their timestamps got updated. So nothing should be purged until we
11663f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        // get kFlushCount additional flushes. Then everything should be purged.
11673f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        for (int i = 0; i < kFlushCount; ++i) {
11683f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            REPORTER_ASSERT(reporter, kFlushCount >> 1 == cache->getResourceCount());
11693f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon            cache->notifyFlushOccurred();
11703f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        }
11713f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
11723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11733f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon        cache->purgeAllUnlocked();
11743f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    }
11753f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
11763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
11773f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon}
11783f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon
117910e23caea3106be125acea10a637789e5a15c728bsalomonstatic void test_large_resource_count(skiatest::Reporter* reporter) {
118010e23caea3106be125acea10a637789e5a15c728bsalomon    // Set the cache size to double the resource count because we're going to create 2x that number
118110e23caea3106be125acea10a637789e5a15c728bsalomon    // resources, using two different key domains. Add a little slop to the bytes because we resize
118210e23caea3106be125acea10a637789e5a15c728bsalomon    // down to 1 byte after creating the resource.
1183c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    static const int kResourceCnt = 2000;
118410e23caea3106be125acea10a637789e5a15c728bsalomon
1185c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    Mock mock(2 * kResourceCnt, 2 * kResourceCnt + 1000);
1186c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    GrContext* context = mock.context();
11870ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    GrResourceCache* cache = mock.cache();
118810e23caea3106be125acea10a637789e5a15c728bsalomon
118910e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
11908718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
11918718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
11928718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
119324db3b1c35fb935660229da164fc5ad31977387fbsalomon
119410e23caea3106be125acea10a637789e5a15c728bsalomon        TestResource* resource;
119510e23caea3106be125acea10a637789e5a15c728bsalomon
1196385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        resource = new TestResource(context->getGpu());
11978718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key1);
119810e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
119910e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
120010e23caea3106be125acea10a637789e5a15c728bsalomon
1201385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        resource = new TestResource(context->getGpu());
12028718aafec239c93485e45bbe8fed19d9a8def079bsalomon        resource->resourcePriv().setUniqueKey(key2);
120310e23caea3106be125acea10a637789e5a15c728bsalomon        resource->setSize(1);
120410e23caea3106be125acea10a637789e5a15c728bsalomon        resource->unref();
120510e23caea3106be125acea10a637789e5a15c728bsalomon    }
120610e23caea3106be125acea10a637789e5a15c728bsalomon
120710e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt);
12080ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 2 * kResourceCnt);
12090ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 2 * kResourceCnt);
12100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 2 * kResourceCnt);
12110ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 2 * kResourceCnt);
121210e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
12138718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
12148718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
12158718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
121624db3b1c35fb935660229da164fc5ad31977387fbsalomon
12178718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key1));
12188718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, cache->hasUniqueKey(key2));
121910e23caea3106be125acea10a637789e5a15c728bsalomon    }
122010e23caea3106be125acea10a637789e5a15c728bsalomon
12210ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    cache->purgeAllUnlocked();
122210e23caea3106be125acea10a637789e5a15c728bsalomon    REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0);
12230ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 0);
12240ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 0);
12250ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceBytes() == 0);
12260ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon    REPORTER_ASSERT(reporter, cache->getResourceCount() == 0);
122710e23caea3106be125acea10a637789e5a15c728bsalomon
122810e23caea3106be125acea10a637789e5a15c728bsalomon    for (int i = 0; i < kResourceCnt; ++i) {
12298718aafec239c93485e45bbe8fed19d9a8def079bsalomon        GrUniqueKey key1, key2;
12308718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<1>(&key1, i);
12318718aafec239c93485e45bbe8fed19d9a8def079bsalomon        make_unique_key<2>(&key2, i);
123224db3b1c35fb935660229da164fc5ad31977387fbsalomon
12338718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key1));
12348718aafec239c93485e45bbe8fed19d9a8def079bsalomon        REPORTER_ASSERT(reporter, !cache->hasUniqueKey(key2));
123510e23caea3106be125acea10a637789e5a15c728bsalomon    }
123610e23caea3106be125acea10a637789e5a15c728bsalomon}
123710e23caea3106be125acea10a637789e5a15c728bsalomon
123884cd621670a357484e1674e06d3d8d6f929a4ab2senorblancostatic void test_custom_data(skiatest::Reporter* reporter) {
123984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key1, key2;
124084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key1, 1);
124184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    make_unique_key<0>(&key2, 2);
124284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    int foo = 4132;
124384cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    SkAutoTUnref<SkData> data(SkData::NewWithCopy(&foo, sizeof(foo)));
124484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    key1.setCustomData(data.get());
124584cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key1.getCustomData()->data() == 4132);
124684cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, key2.getCustomData() == nullptr);
124784cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
124884cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    // Test that copying a key also takes a ref on its custom data.
124984cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    GrUniqueKey key3 = key1;
125084cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132);
125184cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco}
125284cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco
1253c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomonstatic void test_abandoned(skiatest::Reporter* reporter) {
1254c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    Mock mock(10, 300);
1255c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrContext* context = mock.context();
1256c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    TestResource* resource = new TestResource(context->getGpu());
1257c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    context->abandonContext();
1258c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1259c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    REPORTER_ASSERT(reporter, resource->wasDestroyed());
1260c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1261c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    // Call all the public methods on resource in the abandoned state. They shouldn't crash.
1262c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1263c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    int foo = 4132;
1264c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    SkAutoTUnref<SkData> data(SkData::NewWithCopy(&foo, sizeof(foo)));
1265c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->setCustomData(data.get());
1266c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getCustomData();
1267c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getUniqueID();
1268c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getUniqueKey();
1269c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->wasDestroyed();
1270c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->gpuMemorySize();
1271c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->getContext();
1272c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1273c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->abandon();
1274c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().getScratchKey();
1275c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().isBudgeted();
1276c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeBudgeted();
1277c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().makeUnbudgeted();
1278c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeScratchKey();
1279c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    GrUniqueKey key;
1280c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    make_unique_key<0>(&key, 1);
1281c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().setUniqueKey(key);
1282c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    resource->resourcePriv().removeUniqueKey();
1283c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon}
1284c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon
1285c665804300096c2e7617379835bb83d715538788commit-bot@chromium.org////////////////////////////////////////////////////////////////////////////////
12864ee16bfaedb14aff8cf102f1f0722ff2529a9699tfarina@chromium.orgDEF_GPUTEST(ResourceCache, reporter, factory) {
1287c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
1288c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
1289c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        if (!GrContextFactory::IsRenderingGLContext(glType)) {
1290c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org            continue;
1291c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        }
1292c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        GrContext* context = factory->get(glType);
129396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == context) {
1294fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon            continue;
1295fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon        }
1296f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon        GrSurfaceDesc desc;
1297c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        desc.fConfig = kSkia8888_GrPixelConfig;
1298f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon        desc.fFlags = kRenderTarget_GrSurfaceFlag;
1299c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        desc.fWidth = gWidth;
1300c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org        desc.fHeight = gHeight;
130169f6f00fd975823e825c5aa0b1b8f4416e7c812breed        SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
1302afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon        SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context,
1303afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon                                                                   SkSurface::kNo_Budgeted, info));
1304fdcf2c0863cdd5779bd6203d45b77d2daf21f159bsalomon        test_cache(reporter, context, surface->getCanvas());
130502a44a488605112aa6683c9d919e13b188112ce1bsalomon        test_stencil_buffers(reporter, context);
13066dc6f5f4a153d33ed91565cb3cd397a310a937d0bsalomon        test_wrapped_resources(reporter, context);
1307820dd6c335411aad889c1d7e8a857642ecd87e30bsalomon    }
1308334355742137cc238887d4f85856e6c4d9ec8aa8bsalomon
13098b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    // The below tests create their own mock contexts.
131071cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_no_key(reporter);
131184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon    test_budgeting(reporter);
13125236cf480daf82b2f36e42795abdbbc915533a59bsalomon    test_unbudgeted(reporter);
1313c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon    test_unbudgeted_to_scratch(reporter);
13148718aafec239c93485e45bbe8fed19d9a8def079bsalomon    test_duplicate_unique_key(reporter);
13158b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_duplicate_scratch_key(reporter);
131610e23caea3106be125acea10a637789e5a15c728bsalomon    test_remove_scratch_key(reporter);
13171c60dfe7ca0db010fa3118a1a2c7ff4c09136ab0bsalomon    test_scratch_key_consistency(reporter);
13188b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_purge_invalidated(reporter);
131971cb0c241e439b6ed746b90294d0b6916644a644bsalomon    test_cache_chained_purge(reporter);
13208b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon    test_resource_size_changed(reporter);
1321ddf30e64fe474847b204d7062fad3341d245062cbsalomon    test_timestamp_wrap(reporter);
13223f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon    test_flush(reporter);
132310e23caea3106be125acea10a637789e5a15c728bsalomon    test_large_resource_count(reporter);
132484cd621670a357484e1674e06d3d8d6f929a4ab2senorblanco    test_custom_data(reporter);
1325c6363ef7b4763b36a9a0d255bc775a973d2fc7a5bsalomon    test_abandoned(reporter);
1326c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org}
1327c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org
1328c28f555f7f4259216a4a524cae6676ab2c56871acommit-bot@chromium.org#endif
1329