1952841bf41a81228c23d16c7204b458abe0d7136robertphillips/*
2952841bf41a81228c23d16c7204b458abe0d7136robertphillips* Copyright 2014 Google Inc.
3952841bf41a81228c23d16c7204b458abe0d7136robertphillips*
4952841bf41a81228c23d16c7204b458abe0d7136robertphillips* Use of this source code is governed by a BSD-style license that can be
5952841bf41a81228c23d16c7204b458abe0d7136robertphillips* found in the LICENSE file.
6952841bf41a81228c23d16c7204b458abe0d7136robertphillips*/
7952841bf41a81228c23d16c7204b458abe0d7136robertphillips
8952841bf41a81228c23d16c7204b458abe0d7136robertphillips#if SK_SUPPORT_GPU
9952841bf41a81228c23d16c7204b458abe0d7136robertphillips
10952841bf41a81228c23d16c7204b458abe0d7136robertphillips#include "GrContext.h"
11952841bf41a81228c23d16c7204b458abe0d7136robertphillips#include "GrContextFactory.h"
12952841bf41a81228c23d16c7204b458abe0d7136robertphillips#include "GrLayerCache.h"
13cfaeec446d06058cacef068b09f58ae2c78338faRobert Phillips#include "SkPictureRecorder.h"
14952841bf41a81228c23d16c7204b458abe0d7136robertphillips#include "Test.h"
15952841bf41a81228c23d16c7204b458abe0d7136robertphillips
16d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillipsclass TestingAccess {
17952841bf41a81228c23d16c7204b458abe0d7136robertphillipspublic:
18952841bf41a81228c23d16c7204b458abe0d7136robertphillips    static int NumLayers(GrLayerCache* cache) {
19952841bf41a81228c23d16c7204b458abe0d7136robertphillips        return cache->numLayers();
20952841bf41a81228c23d16c7204b458abe0d7136robertphillips    }
21d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips    static void Purge(GrLayerCache* cache, uint32_t pictureID) {
22d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        cache->purge(pictureID);
23d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips    }
24952841bf41a81228c23d16c7204b458abe0d7136robertphillips};
25952841bf41a81228c23d16c7204b458abe0d7136robertphillips
26952841bf41a81228c23d16c7204b458abe0d7136robertphillips// Add several layers to the cache
27952841bf41a81228c23d16c7204b458abe0d7136robertphillipsstatic void create_layers(skiatest::Reporter* reporter,
28952841bf41a81228c23d16c7204b458abe0d7136robertphillips                          GrLayerCache* cache,
29320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                          const SkPicture& picture,
30320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                          int numToAdd,
31320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                          int idOffset) {
32320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
33320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    for (int i = 0; i < numToAdd; ++i) {
346f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips        GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
350c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips                                                        idOffset+i+1, idOffset+i+2,
364815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                                        SkIPoint::Make(0, 0),
374aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips                                                        SkMatrix::I(),
384aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips                                                        NULL);
3949f085dddff10473b6ebf832a974288300224e60bsalomon        REPORTER_ASSERT(reporter, layer);
404815fe5a0a497b676677fb4e4a0f05c511855490robertphillips        GrCachedLayer* temp = cache->findLayer(picture.uniqueID(), idOffset+i+1, idOffset+i+2,
414815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                               SkIPoint::Make(0, 0), SkMatrix::I());
42320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        REPORTER_ASSERT(reporter, temp == layer);
43320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
44320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
45320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
46320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
470c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips        REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
480c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips        REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
490c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips        REPORTER_ASSERT(reporter, layer->ctm() == SkMatrix::I());
50320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        REPORTER_ASSERT(reporter, NULL == layer->texture());
514aa6dfc0b77af9ac298bb9d48991b72a2fec00b2robertphillips        REPORTER_ASSERT(reporter, NULL == layer->paint());
52320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        REPORTER_ASSERT(reporter, !layer->isAtlased());
53320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    }
54320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
55320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    cache->trackPicture(&picture);
56320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips}
57952841bf41a81228c23d16c7204b458abe0d7136robertphillips
58320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillipsstatic void lock_layer(skiatest::Reporter* reporter,
59320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                       GrLayerCache* cache,
60320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                       GrCachedLayer* layer) {
61320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    // Make the layer 512x512 (so it can be atlased)
62320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    GrTextureDesc desc;
63320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    desc.fWidth = 512;
64320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    desc.fHeight = 512;
65320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    desc.fConfig = kSkia8888_GrPixelConfig;
66952841bf41a81228c23d16c7204b458abe0d7136robertphillips
676f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips    bool needsRerendering = cache->lock(layer, desc, false);
686f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips    REPORTER_ASSERT(reporter, needsRerendering);
69952841bf41a81228c23d16c7204b458abe0d7136robertphillips
706f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips    needsRerendering = cache->lock(layer, desc, false);
716f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips    REPORTER_ASSERT(reporter, !needsRerendering);
72952841bf41a81228c23d16c7204b458abe0d7136robertphillips
7349f085dddff10473b6ebf832a974288300224e60bsalomon    REPORTER_ASSERT(reporter, layer->texture());
74320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    REPORTER_ASSERT(reporter, layer->locked());
75952841bf41a81228c23d16c7204b458abe0d7136robertphillips}
76952841bf41a81228c23d16c7204b458abe0d7136robertphillips
77952841bf41a81228c23d16c7204b458abe0d7136robertphillips// This test case exercises the public API of the GrLayerCache class.
78952841bf41a81228c23d16c7204b458abe0d7136robertphillips// In particular it checks its interaction with the resource cache (w.r.t.
79952841bf41a81228c23d16c7204b458abe0d7136robertphillips// locking & unlocking textures).
80952841bf41a81228c23d16c7204b458abe0d7136robertphillips// TODO: need to add checks on VRAM usage!
81952841bf41a81228c23d16c7204b458abe0d7136robertphillipsDEF_GPUTEST(GpuLayerCache, reporter, factory) {
82320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips    static const int kInitialNumLayers = 5;
83320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
84e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon    for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
85e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
86952841bf41a81228c23d16c7204b458abe0d7136robertphillips
87e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
88e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            continue;
89e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        }
90952841bf41a81228c23d16c7204b458abe0d7136robertphillips
91e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        GrContext* context = factory->get(glCtxType);
92952841bf41a81228c23d16c7204b458abe0d7136robertphillips
93e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        if (NULL == context) {
94e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            continue;
95e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        }
96952841bf41a81228c23d16c7204b458abe0d7136robertphillips
97e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        SkPictureRecorder recorder;
98e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        recorder.beginRecording(1, 1);
99e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
100952841bf41a81228c23d16c7204b458abe0d7136robertphillips
101e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        GrLayerCache cache(context);
102952841bf41a81228c23d16c7204b458abe0d7136robertphillips
103320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
104e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon
105320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        for (int i = 0; i < kInitialNumLayers; ++i) {
1064815fe5a0a497b676677fb4e4a0f05c511855490robertphillips            GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
1074815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                                   SkIPoint::Make(0, 0), SkMatrix::I());
10849f085dddff10473b6ebf832a974288300224e60bsalomon            REPORTER_ASSERT(reporter, layer);
109952841bf41a81228c23d16c7204b458abe0d7136robertphillips
110320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            lock_layer(reporter, &cache, layer);
111e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon
112e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            // The first 4 layers should be in the atlas (and thus have non-empty
113e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            // rects)
114e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            if (i < 4) {
115e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon                REPORTER_ASSERT(reporter, layer->isAtlased());
116e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            } else {
117320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                // The 5th layer couldn't fit in the atlas
118320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                REPORTER_ASSERT(reporter, !layer->isAtlased());
119e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            }
120e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        }
121952841bf41a81228c23d16c7204b458abe0d7136robertphillips
122e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // Unlock the textures
123320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        for (int i = 0; i < kInitialNumLayers; ++i) {
1244815fe5a0a497b676677fb4e4a0f05c511855490robertphillips            GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
1254815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                                   SkIPoint::Make(0, 0), SkMatrix::I());
12649f085dddff10473b6ebf832a974288300224e60bsalomon            REPORTER_ASSERT(reporter, layer);
127e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            cache.unlock(layer);
128e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        }
129952841bf41a81228c23d16c7204b458abe0d7136robertphillips
130320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        for (int i = 0; i < kInitialNumLayers; ++i) {
1314815fe5a0a497b676677fb4e4a0f05c511855490robertphillips            GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
1324815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                                   SkIPoint::Make(0, 0), SkMatrix::I());
13349f085dddff10473b6ebf832a974288300224e60bsalomon            REPORTER_ASSERT(reporter, layer);
134952841bf41a81228c23d16c7204b458abe0d7136robertphillips
135320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            REPORTER_ASSERT(reporter, !layer->locked());
136320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            // The first 4 layers should still be in the atlas.
137e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            if (i < 4) {
13849f085dddff10473b6ebf832a974288300224e60bsalomon                REPORTER_ASSERT(reporter, layer->texture());
139e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon                REPORTER_ASSERT(reporter, layer->isAtlased());
140e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            } else {
141320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                // The final layer should be unlocked.
142e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon                REPORTER_ASSERT(reporter, NULL == layer->texture());
143e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon                REPORTER_ASSERT(reporter, !layer->isAtlased());
144e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon            }
145e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        }
146952841bf41a81228c23d16c7204b458abe0d7136robertphillips
147320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        {
148320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            // Add an additional layer. Since all the layers are unlocked this
149320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            // will force out the first atlased layer
150320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
1516f294af43bcd94ed9616a7e4f5892589813d0a01robertphillips            GrCachedLayer* layer = cache.findLayer(picture->uniqueID(),
1520c4233285919c10df63c6cb207e580a7d1ff66b4robertphillips                                                   kInitialNumLayers+1, kInitialNumLayers+2,
1534815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                                   SkIPoint::Make(0, 0), SkMatrix::I());
15449f085dddff10473b6ebf832a974288300224e60bsalomon            REPORTER_ASSERT(reporter, layer);
155320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
156320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            lock_layer(reporter, &cache, layer);
157320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            cache.unlock(layer);
158320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        }
159320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
160320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        for (int i = 0; i < kInitialNumLayers+1; ++i) {
1614815fe5a0a497b676677fb4e4a0f05c511855490robertphillips            GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2,
1624815fe5a0a497b676677fb4e4a0f05c511855490robertphillips                                                   SkIPoint::Make(0, 0), SkMatrix::I());
163320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            // 3 old layers plus the new one should be in the atlas.
164320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            if (1 == i || 2 == i || 3 == i || 5 == i) {
16549f085dddff10473b6ebf832a974288300224e60bsalomon                REPORTER_ASSERT(reporter, layer);
166320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                REPORTER_ASSERT(reporter, !layer->locked());
16749f085dddff10473b6ebf832a974288300224e60bsalomon                REPORTER_ASSERT(reporter, layer->texture());
168320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                REPORTER_ASSERT(reporter, layer->isAtlased());
169320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            } else if (4 == i) {
170320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                // The one that was never atlased should still be around
17149f085dddff10473b6ebf832a974288300224e60bsalomon                REPORTER_ASSERT(reporter, layer);
172320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
173320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                REPORTER_ASSERT(reporter, NULL == layer->texture());
174320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                REPORTER_ASSERT(reporter, !layer->isAtlased());
175320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            } else {
176320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                // The one bumped out of the atlas (i.e., 0) should be gone
177320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips                REPORTER_ASSERT(reporter, NULL == layer);
178320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips            }
179320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        }
180320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips
181d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        //--------------------------------------------------------------------
182e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // Free them all SkGpuDevice-style. This will not free up the
183e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // atlas' texture but will eliminate all the layers.
184d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        TestingAccess::Purge(&cache, picture->uniqueID());
185952841bf41a81228c23d16c7204b458abe0d7136robertphillips
186d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
187e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // TODO: add VRAM/resource cache check here
188d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips
189d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        //--------------------------------------------------------------------
190d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        // Test out the GrContext-style purge. This should remove all the layers
191d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        // and the atlas.
192e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // Re-create the layers
193320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
194952841bf41a81228c23d16c7204b458abe0d7136robertphillips
195e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // Free them again GrContext-style. This should free up everything.
196e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        cache.freeAll();
197952841bf41a81228c23d16c7204b458abe0d7136robertphillips
198d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
199d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        // TODO: add VRAM/resource cache check here
200d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips
201d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        //--------------------------------------------------------------------
202d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        // Test out the MessageBus-style purge. This will not free the atlas
203d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        // but should eliminate the free-floating layers.
204320c92380fe6a43dffbcd3f9e7c99897da44298drobertphillips        create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
205d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips
206d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        picture.reset(NULL);
207d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        cache.processDeletedPictures();
208d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips
209d771f6bc273457bc7aa95938ac326dfbbf876e1arobertphillips        REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
210e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon        // TODO: add VRAM/resource cache check here
211e904c09a3a9c701e8d91f2f6ee161feda7615d90bsalomon    }
212952841bf41a81228c23d16c7204b458abe0d7136robertphillips}
213952841bf41a81228c23d16c7204b458abe0d7136robertphillips
214952841bf41a81228c23d16c7204b458abe0d7136robertphillips#endif
215