blob: efb1ec1c203e44570d66c37a025fca3d7ff873f6 [file] [log] [blame]
robertphillips952841b2014-06-30 08:26:50 -07001/*
2* Copyright 2014 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#if SK_SUPPORT_GPU
9
10#include "GrContext.h"
11#include "GrContextFactory.h"
12#include "GrLayerCache.h"
Robert Phillipscfaeec42014-07-13 12:00:50 -040013#include "SkPictureRecorder.h"
robertphillips952841b2014-06-30 08:26:50 -070014#include "Test.h"
15
robertphillipsd771f6b2014-07-22 10:18:06 -070016class TestingAccess {
robertphillips952841b2014-06-30 08:26:50 -070017public:
robertphillipse99d4992014-12-03 07:33:57 -080018 static unsigned NumLayers(GrLayerCache* cache) {
robertphillips952841b2014-06-30 08:26:50 -070019 return cache->numLayers();
20 }
robertphillipsd771f6b2014-07-22 10:18:06 -070021 static void Purge(GrLayerCache* cache, uint32_t pictureID) {
22 cache->purge(pictureID);
23 }
robertphillips7bb9ed72014-10-10 11:38:29 -070024 static int Uses(GrCachedLayer* layer) {
25 return layer->uses();
26 }
robertphillips01d6e5f2014-12-01 09:09:27 -080027 static GrCachedLayer* Find(GrLayerCache* cache, uint32_t pictureID,
robertphillipse99d4992014-12-03 07:33:57 -080028 const SkMatrix& initialMat,
29 const unsigned* key, int keySize) {
robertphillips01d6e5f2014-12-01 09:09:27 -080030 return cache->findLayer(pictureID, initialMat, key, keySize);
31 }
robertphillips952841b2014-06-30 08:26:50 -070032};
33
34// Add several layers to the cache
35static void create_layers(skiatest::Reporter* reporter,
36 GrLayerCache* cache,
robertphillips320c9232014-07-29 06:07:19 -070037 const SkPicture& picture,
robertphillipse99d4992014-12-03 07:33:57 -080038 unsigned numToAdd,
39 unsigned idOffset) {
robertphillips952841b2014-06-30 08:26:50 -070040
robertphillipse99d4992014-12-03 07:33:57 -080041 for (unsigned i = 0; i < numToAdd; ++i) {
42 unsigned indices[1] = { idOffset+i+1 };
robertphillips6f294af2014-08-18 08:50:03 -070043 GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
robertphillips0c423322014-07-31 11:02:38 -070044 idOffset+i+1, idOffset+i+2,
robertphillips3aac6e02014-10-20 08:52:40 -070045 SkIRect::MakeEmpty(),
robertphillips478dd722014-12-16 08:25:55 -080046 SkIRect::MakeEmpty(),
robertphillips4aa6dfc2014-09-17 07:50:47 -070047 SkMatrix::I(),
robertphillips01d6e5f2014-12-01 09:09:27 -080048 indices, 1,
robertphillips4aa6dfc2014-09-17 07:50:47 -070049 NULL);
bsalomon49f085d2014-09-05 13:34:00 -070050 REPORTER_ASSERT(reporter, layer);
robertphillips01d6e5f2014-12-01 09:09:27 -080051 GrCachedLayer* temp = TestingAccess::Find(cache, picture.uniqueID(), SkMatrix::I(),
52 indices, 1);
robertphillips320c9232014-07-29 06:07:19 -070053 REPORTER_ASSERT(reporter, temp == layer);
robertphillips952841b2014-06-30 08:26:50 -070054
robertphillips320c9232014-07-29 06:07:19 -070055 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
robertphillips952841b2014-06-30 08:26:50 -070056
robertphillips320c9232014-07-29 06:07:19 -070057 REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
robertphillips0c423322014-07-31 11:02:38 -070058 REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
59 REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
robertphillips320c9232014-07-29 06:07:19 -070060 REPORTER_ASSERT(reporter, NULL == layer->texture());
robertphillips4aa6dfc2014-09-17 07:50:47 -070061 REPORTER_ASSERT(reporter, NULL == layer->paint());
robertphillips320c9232014-07-29 06:07:19 -070062 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips952841b2014-06-30 08:26:50 -070063 }
robertphillips952841b2014-06-30 08:26:50 -070064}
65
robertphillips320c9232014-07-29 06:07:19 -070066static void lock_layer(skiatest::Reporter* reporter,
67 GrLayerCache* cache,
68 GrCachedLayer* layer) {
69 // Make the layer 512x512 (so it can be atlased)
bsalomonf2703d82014-10-28 14:33:06 -070070 GrSurfaceDesc desc;
robertphillips320c9232014-07-29 06:07:19 -070071 desc.fWidth = 512;
72 desc.fHeight = 512;
73 desc.fConfig = kSkia8888_GrPixelConfig;
74
robertphillipsfd61ed02014-10-28 07:21:44 -070075 bool needsRerendering;
76 bool inAtlas = cache->tryToAtlas(layer, desc, &needsRerendering);
77 if (!inAtlas) {
78 cache->lock(layer, desc, &needsRerendering);
79 }
robertphillips6f294af2014-08-18 08:50:03 -070080 REPORTER_ASSERT(reporter, needsRerendering);
robertphillips320c9232014-07-29 06:07:19 -070081
robertphillipsfd61ed02014-10-28 07:21:44 -070082 cache->lock(layer, desc, &needsRerendering);
robertphillips6f294af2014-08-18 08:50:03 -070083 REPORTER_ASSERT(reporter, !needsRerendering);
robertphillips320c9232014-07-29 06:07:19 -070084
bsalomon49f085d2014-09-05 13:34:00 -070085 REPORTER_ASSERT(reporter, layer->texture());
robertphillips320c9232014-07-29 06:07:19 -070086 REPORTER_ASSERT(reporter, layer->locked());
robertphillips7bb9ed72014-10-10 11:38:29 -070087
88 cache->addUse(layer);
89
90 REPORTER_ASSERT(reporter, 1 == TestingAccess::Uses(layer));
robertphillips320c9232014-07-29 06:07:19 -070091}
92
robertphillips952841b2014-06-30 08:26:50 -070093// This test case exercises the public API of the GrLayerCache class.
94// In particular it checks its interaction with the resource cache (w.r.t.
95// locking & unlocking textures).
96// TODO: need to add checks on VRAM usage!
97DEF_GPUTEST(GpuLayerCache, reporter, factory) {
kkinnunenb5f49612014-12-12 05:29:12 -080098 static const unsigned kInitialNumLayers = 5;
robertphillips320c9232014-07-29 06:07:19 -070099
bsalomone904c092014-07-17 10:50:59 -0700100 for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
101 GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
robertphillips952841b2014-06-30 08:26:50 -0700102
bsalomone904c092014-07-17 10:50:59 -0700103 if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
104 continue;
robertphillips952841b2014-06-30 08:26:50 -0700105 }
robertphillips952841b2014-06-30 08:26:50 -0700106
bsalomone904c092014-07-17 10:50:59 -0700107 GrContext* context = factory->get(glCtxType);
robertphillips952841b2014-06-30 08:26:50 -0700108
bsalomone904c092014-07-17 10:50:59 -0700109 if (NULL == context) {
110 continue;
111 }
robertphillips952841b2014-06-30 08:26:50 -0700112
bsalomone904c092014-07-17 10:50:59 -0700113 SkPictureRecorder recorder;
mtklein9db912c2015-05-19 11:11:26 -0700114 SkCanvas* c = recorder.beginRecording(1, 1);
115 // Draw something, anything, to prevent an empty-picture optimization,
116 // which is a singleton and never purged.
117 c->drawRect(SkRect::MakeWH(1,1), SkPaint());
bsalomone904c092014-07-17 10:50:59 -0700118 SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
robertphillips952841b2014-06-30 08:26:50 -0700119
bsalomone904c092014-07-17 10:50:59 -0700120 GrLayerCache cache(context);
121
robertphillips320c9232014-07-29 06:07:19 -0700122 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
bsalomone904c092014-07-17 10:50:59 -0700123
robertphillipse99d4992014-12-03 07:33:57 -0800124 for (unsigned i = 0; i < kInitialNumLayers; ++i) {
125 unsigned indices[1] = { i + 1 };
robertphillips01d6e5f2014-12-01 09:09:27 -0800126 GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
127 indices, 1);
bsalomon49f085d2014-09-05 13:34:00 -0700128 REPORTER_ASSERT(reporter, layer);
bsalomone904c092014-07-17 10:50:59 -0700129
robertphillips320c9232014-07-29 06:07:19 -0700130 lock_layer(reporter, &cache, layer);
bsalomone904c092014-07-17 10:50:59 -0700131
bsalomone904c092014-07-17 10:50:59 -0700132 // The first 4 layers should be in the atlas (and thus have non-empty
133 // rects)
134 if (i < 4) {
135 REPORTER_ASSERT(reporter, layer->isAtlased());
136 } else {
robertphillips320c9232014-07-29 06:07:19 -0700137 // The 5th layer couldn't fit in the atlas
138 REPORTER_ASSERT(reporter, !layer->isAtlased());
bsalomone904c092014-07-17 10:50:59 -0700139 }
robertphillips952841b2014-06-30 08:26:50 -0700140 }
bsalomone904c092014-07-17 10:50:59 -0700141
142 // Unlock the textures
robertphillipse99d4992014-12-03 07:33:57 -0800143 for (unsigned i = 0; i < kInitialNumLayers; ++i) {
144 unsigned indices[1] = { i+1 };
robertphillips01d6e5f2014-12-01 09:09:27 -0800145
146 GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
147 indices, 1);
bsalomon49f085d2014-09-05 13:34:00 -0700148 REPORTER_ASSERT(reporter, layer);
robertphillips7bb9ed72014-10-10 11:38:29 -0700149 cache.removeUse(layer);
bsalomone904c092014-07-17 10:50:59 -0700150 }
151
robertphillipse99d4992014-12-03 07:33:57 -0800152 for (unsigned i = 0; i < kInitialNumLayers; ++i) {
153 unsigned indices[1] = { i+1 };
robertphillips01d6e5f2014-12-01 09:09:27 -0800154
155 GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
156 indices, 1);
bsalomon49f085d2014-09-05 13:34:00 -0700157 REPORTER_ASSERT(reporter, layer);
bsalomone904c092014-07-17 10:50:59 -0700158
robertphillips7bb9ed72014-10-10 11:38:29 -0700159 // All the layers should be unlocked
robertphillips320c9232014-07-29 06:07:19 -0700160 REPORTER_ASSERT(reporter, !layer->locked());
robertphillips7bb9ed72014-10-10 11:38:29 -0700161
robertphillips4ab5a902014-10-29 13:56:02 -0700162 // When hoisted layers aren't cached they are aggressively removed
163 // from the atlas
164#if GR_CACHE_HOISTED_LAYERS
robertphillips320c9232014-07-29 06:07:19 -0700165 // The first 4 layers should still be in the atlas.
bsalomone904c092014-07-17 10:50:59 -0700166 if (i < 4) {
bsalomon49f085d2014-09-05 13:34:00 -0700167 REPORTER_ASSERT(reporter, layer->texture());
bsalomone904c092014-07-17 10:50:59 -0700168 REPORTER_ASSERT(reporter, layer->isAtlased());
169 } else {
robertphillips4ab5a902014-10-29 13:56:02 -0700170#endif
robertphillips7bb9ed72014-10-10 11:38:29 -0700171 // The final layer should not be atlased.
bsalomone904c092014-07-17 10:50:59 -0700172 REPORTER_ASSERT(reporter, NULL == layer->texture());
173 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips4ab5a902014-10-29 13:56:02 -0700174#if GR_CACHE_HOISTED_LAYERS
bsalomone904c092014-07-17 10:50:59 -0700175 }
robertphillips4ab5a902014-10-29 13:56:02 -0700176#endif
bsalomone904c092014-07-17 10:50:59 -0700177 }
178
robertphillips320c9232014-07-29 06:07:19 -0700179 {
robertphillipse99d4992014-12-03 07:33:57 -0800180 unsigned indices[1] = { kInitialNumLayers+1 };
robertphillips01d6e5f2014-12-01 09:09:27 -0800181
robertphillips320c9232014-07-29 06:07:19 -0700182 // Add an additional layer. Since all the layers are unlocked this
183 // will force out the first atlased layer
184 create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
robertphillips01d6e5f2014-12-01 09:09:27 -0800185 GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
186 indices, 1);
bsalomon49f085d2014-09-05 13:34:00 -0700187 REPORTER_ASSERT(reporter, layer);
robertphillips320c9232014-07-29 06:07:19 -0700188
189 lock_layer(reporter, &cache, layer);
robertphillips7bb9ed72014-10-10 11:38:29 -0700190 cache.removeUse(layer);
robertphillips320c9232014-07-29 06:07:19 -0700191 }
192
robertphillipse99d4992014-12-03 07:33:57 -0800193 for (unsigned i = 0; i < kInitialNumLayers+1; ++i) {
194 unsigned indices[1] = { i+1 };
robertphillips01d6e5f2014-12-01 09:09:27 -0800195
196 GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
197 indices, 1);
robertphillips4ab5a902014-10-29 13:56:02 -0700198#if GR_CACHE_HOISTED_LAYERS
robertphillips320c9232014-07-29 06:07:19 -0700199 // 3 old layers plus the new one should be in the atlas.
200 if (1 == i || 2 == i || 3 == i || 5 == i) {
bsalomon49f085d2014-09-05 13:34:00 -0700201 REPORTER_ASSERT(reporter, layer);
robertphillips320c9232014-07-29 06:07:19 -0700202 REPORTER_ASSERT(reporter, !layer->locked());
bsalomon49f085d2014-09-05 13:34:00 -0700203 REPORTER_ASSERT(reporter, layer->texture());
robertphillips320c9232014-07-29 06:07:19 -0700204 REPORTER_ASSERT(reporter, layer->isAtlased());
205 } else if (4 == i) {
robertphillips4ab5a902014-10-29 13:56:02 -0700206#endif
robertphillips320c9232014-07-29 06:07:19 -0700207 // The one that was never atlased should still be around
bsalomon49f085d2014-09-05 13:34:00 -0700208 REPORTER_ASSERT(reporter, layer);
robertphillips320c9232014-07-29 06:07:19 -0700209
210 REPORTER_ASSERT(reporter, NULL == layer->texture());
211 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips4ab5a902014-10-29 13:56:02 -0700212#if GR_CACHE_HOISTED_LAYERS
robertphillips320c9232014-07-29 06:07:19 -0700213 } else {
214 // The one bumped out of the atlas (i.e., 0) should be gone
215 REPORTER_ASSERT(reporter, NULL == layer);
216 }
robertphillips4ab5a902014-10-29 13:56:02 -0700217#endif
robertphillips320c9232014-07-29 06:07:19 -0700218 }
219
robertphillipsd771f6b2014-07-22 10:18:06 -0700220 //--------------------------------------------------------------------
bsalomone904c092014-07-17 10:50:59 -0700221 // Free them all SkGpuDevice-style. This will not free up the
222 // atlas' texture but will eliminate all the layers.
robertphillipsd771f6b2014-07-22 10:18:06 -0700223 TestingAccess::Purge(&cache, picture->uniqueID());
bsalomone904c092014-07-17 10:50:59 -0700224
robertphillipsd771f6b2014-07-22 10:18:06 -0700225 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
bsalomone904c092014-07-17 10:50:59 -0700226 // TODO: add VRAM/resource cache check here
robertphillipsd771f6b2014-07-22 10:18:06 -0700227
228 //--------------------------------------------------------------------
229 // Test out the GrContext-style purge. This should remove all the layers
230 // and the atlas.
bsalomone904c092014-07-17 10:50:59 -0700231 // Re-create the layers
robertphillips320c9232014-07-29 06:07:19 -0700232 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
bsalomone904c092014-07-17 10:50:59 -0700233
234 // Free them again GrContext-style. This should free up everything.
235 cache.freeAll();
236
robertphillipsd771f6b2014-07-22 10:18:06 -0700237 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
bsalomone904c092014-07-17 10:50:59 -0700238 // TODO: add VRAM/resource cache check here
robertphillipsd771f6b2014-07-22 10:18:06 -0700239
240 //--------------------------------------------------------------------
241 // Test out the MessageBus-style purge. This will not free the atlas
242 // but should eliminate the free-floating layers.
robertphillips320c9232014-07-29 06:07:19 -0700243 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
robertphillipsd771f6b2014-07-22 10:18:06 -0700244
245 picture.reset(NULL);
246 cache.processDeletedPictures();
247
248 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
249 // TODO: add VRAM/resource cache check here
robertphillips952841b2014-06-30 08:26:50 -0700250 }
robertphillips952841b2014-06-30 08:26:50 -0700251}
252
253#endif