• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 // Disabling this test since it is for the layer hoister which is current disabled.
9 // The test fails when we add a discard to a newly created render target.
10 #if 0
11 
12 #include "GrContext.h"
13 #include "GrLayerCache.h"
14 #include "GrResourceCache.h"
15 #include "SkPictureRecorder.h"
16 #include "Test.h"
17 
18 class TestingAccess {
19 public:
20     static int NumPlots() {
21         return GrLayerCache::kNumPlotsX * GrLayerCache::kNumPlotsY;
22     }
23     static SkISize PlotSize() {
24         return SkISize::Make(GrLayerCache::kAtlasTextureWidth / GrLayerCache::kNumPlotsX,
25                              GrLayerCache::kAtlasTextureHeight / GrLayerCache::kNumPlotsY);
26     }
27 
28     static GrTexture* GetBackingTexture(GrLayerCache* cache) {
29         return cache->fAtlas->getTextureOrNull();
30     }
31 
32     static int NumLayers(GrLayerCache* cache) {
33         return cache->numLayers();
34     }
35     static void Purge(GrLayerCache* cache, uint32_t pictureID) {
36         cache->purge(pictureID);
37     }
38     static int Uses(GrCachedLayer* layer) {
39         return layer->uses();
40     }
41     static GrCachedLayer* Find(GrLayerCache* cache, uint32_t pictureID,
42                                const SkMatrix& initialMat,
43                                const int* key, int keySize) {
44         return cache->findLayer(pictureID, initialMat, key, keySize);
45     }
46 };
47 
48 // Add several layers to the cache
49 static void create_layers(skiatest::Reporter* reporter,
50                           GrLayerCache* cache,
51                           const SkPicture& picture,
52                           int numToAdd,
53                           int idOffset) {
54 
55     for (int i = 0; i < numToAdd; ++i) {
56         int key[1] = { idOffset+i+1 };
57         GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
58                                                         idOffset+i+1, idOffset+i+2,
59                                                         SkIRect::MakeEmpty(),
60                                                         SkIRect::MakeEmpty(),
61                                                         SkMatrix::I(),
62                                                         key, 1,
63                                                         nullptr);
64         REPORTER_ASSERT(reporter, layer);
65         GrCachedLayer* temp = TestingAccess::Find(cache, picture.uniqueID(), SkMatrix::I(),
66                                                   key, 1);
67         REPORTER_ASSERT(reporter, temp == layer);
68 
69         REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
70 
71         REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
72         REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
73         REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
74         REPORTER_ASSERT(reporter, !layer->texture());
75         REPORTER_ASSERT(reporter, !layer->paint());
76         REPORTER_ASSERT(reporter, !layer->isAtlased());
77     }
78 }
79 
80 static void lock_layer(skiatest::Reporter* reporter,
81                        GrLayerCache* cache,
82                        GrCachedLayer* layer) {
83     // Make each layer big enough to consume one whole plot in the atlas
84     GrSurfaceDesc desc;
85     desc.fFlags = kRenderTarget_GrSurfaceFlag;
86     desc.fWidth = TestingAccess::PlotSize().fWidth;
87     desc.fHeight = TestingAccess::PlotSize().fHeight;
88     desc.fConfig = kSkia8888_GrPixelConfig;
89 
90     bool needsRerendering;
91     bool inAtlas = cache->tryToAtlas(layer, desc, &needsRerendering);
92     if (!inAtlas) {
93         cache->lock(layer, desc, &needsRerendering);
94     }
95     REPORTER_ASSERT(reporter, needsRerendering);
96 
97     cache->lock(layer, desc, &needsRerendering);
98     REPORTER_ASSERT(reporter, !needsRerendering);
99 
100     REPORTER_ASSERT(reporter, layer->texture());
101     REPORTER_ASSERT(reporter, layer->locked());
102 
103     cache->addUse(layer);
104 
105     REPORTER_ASSERT(reporter, 1 == TestingAccess::Uses(layer));
106 }
107 
108 // This test case exercises the public API of the GrLayerCache class.
109 // In particular it checks its interaction with the resource cache (w.r.t.
110 // locking & unlocking textures).
111 // TODO: need to add checks on VRAM usage!
112 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GpuLayerCache, reporter, ctxInfo) {
113     // Add one more layer than can fit in the atlas
114     static const int kInitialNumLayers = TestingAccess::NumPlots() + 1;
115 
116 #if GR_CACHE_STATS
117     GrResourceCache::Stats stats;
118 #endif
119 
120     sk_sp<SkPicture> picture;
121 
122     {
123         SkPictureRecorder recorder;
124         SkCanvas* c = recorder.beginRecording(1, 1);
125         // Draw something, anything, to prevent an empty-picture optimization,
126         // which is a singleton and never purged.
127         c->drawRect(SkRect::MakeWH(1,1), SkPaint());
128         picture = recorder.finishRecordingAsPicture();
129     }
130 
131     GrResourceCache* resourceCache = ctxInfo.grContext()->getResourceCache();
132 
133     GrLayerCache cache(ctxInfo.grContext());
134 
135     create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
136 
137     for (int i = 0; i < kInitialNumLayers; ++i) {
138         int key[1] = { i + 1 };
139         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
140                                                    key, 1);
141         REPORTER_ASSERT(reporter, layer);
142 
143         lock_layer(reporter, &cache, layer);
144 
145 #if GR_CACHE_STATS
146         resourceCache->getStats(&stats);
147 #endif
148 
149         // The first 4 layers should be in the atlas (and thus have non-empty rects)
150         if (i < TestingAccess::NumPlots()) {
151             REPORTER_ASSERT(reporter, layer->isAtlased());
152 #if GR_CACHE_STATS
153             REPORTER_ASSERT(reporter, 1 == stats.fTotal);
154 #endif
155         } else {
156             // The 5th layer couldn't fit in the atlas
157             REPORTER_ASSERT(reporter, !layer->isAtlased());
158 #if GR_CACHE_STATS
159             REPORTER_ASSERT(reporter, 2 == stats.fTotal);
160 #endif
161         }
162     }
163 
164     // Unlock the textures
165     for (int i = 0; i < kInitialNumLayers; ++i) {
166         int key[1] = { i+1 };
167 
168         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
169                                                    key, 1);
170         REPORTER_ASSERT(reporter, layer);
171         cache.removeUse(layer);
172     }
173 
174 #if GR_CACHE_STATS
175     resourceCache->getStats(&stats);
176     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
177     // The floating layer is purgeable the cache is not
178     REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
179     REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
180 #endif
181 
182     for (int i = 0; i < kInitialNumLayers; ++i) {
183         int key[1] = { i+1 };
184 
185         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
186                                                    key, 1);
187         REPORTER_ASSERT(reporter, layer);
188 
189         // All the layers should be unlocked
190         REPORTER_ASSERT(reporter, !layer->locked());
191 
192         // When hoisted layers aren't cached they are aggressively removed
193         // from the atlas
194 #if GR_CACHE_HOISTED_LAYERS
195         // The first 4 layers should still be in the atlas.
196         if (i < 4) {
197             REPORTER_ASSERT(reporter, layer->texture());
198             REPORTER_ASSERT(reporter, layer->isAtlased());
199         } else {
200 #endif
201             // The final layer should not be atlased.
202             REPORTER_ASSERT(reporter, !layer->texture());
203             REPORTER_ASSERT(reporter, !layer->isAtlased());
204 #if GR_CACHE_HOISTED_LAYERS
205         }
206 #endif
207     }
208 
209     // Let go of the backing texture
210     cache.end();
211     REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));
212 
213 #if GR_CACHE_STATS
214     resourceCache->getStats(&stats);
215     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
216     // Now both the floater and the atlas are purgeable
217     REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
218 #endif
219 
220     // re-attach to the backing texture
221     cache.begin();
222     REPORTER_ASSERT(reporter, TestingAccess::GetBackingTexture(&cache));
223 
224 #if GR_CACHE_STATS
225     resourceCache->getStats(&stats);
226     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
227     // The atlas is restored to being non-purgeable
228     REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
229     REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
230 #endif
231 
232     {
233         int key[1] = { kInitialNumLayers+1 };
234 
235         // Add an additional layer. Since all the layers are unlocked this
236         // will force out the first atlased layer
237         create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
238         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
239                                                    key, 1);
240         REPORTER_ASSERT(reporter, layer);
241 
242         lock_layer(reporter, &cache, layer);
243         cache.removeUse(layer);
244     }
245 
246     for (int i = 0; i < kInitialNumLayers+1; ++i) {
247         int key[1] = { i+1 };
248 
249         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
250                                                    key, 1);
251 #if GR_CACHE_HOISTED_LAYERS
252         // 3 old layers plus the new one should be in the atlas.
253         if (1 == i || 2 == i || 3 == i || 5 == i) {
254             REPORTER_ASSERT(reporter, layer);
255             REPORTER_ASSERT(reporter, !layer->locked());
256             REPORTER_ASSERT(reporter, layer->texture());
257             REPORTER_ASSERT(reporter, layer->isAtlased());
258         } else if (4 == i) {
259 #endif
260             // The one that was never atlased should still be around
261             REPORTER_ASSERT(reporter, layer);
262 
263             REPORTER_ASSERT(reporter, !layer->texture());
264             REPORTER_ASSERT(reporter, !layer->isAtlased());
265 #if GR_CACHE_HOISTED_LAYERS
266         } else {
267             // The one bumped out of the atlas (i.e., 0) should be gone
268             REPORTER_ASSERT(reporter, nullptr == layer);
269         }
270 #endif
271     }
272 
273     //--------------------------------------------------------------------
274     // Free them all SkGpuDevice-style. This will not free up the
275     // atlas' texture but will eliminate all the layers.
276     TestingAccess::Purge(&cache, picture->uniqueID());
277 
278     REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
279 
280 #if GR_CACHE_STATS
281     resourceCache->getStats(&stats);
282     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
283     // Atlas isn't purgeable
284     REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
285     REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
286 #endif
287 
288     //--------------------------------------------------------------------
289     // Test out the GrContext-style purge. This should remove all the layers
290     // and the atlas.
291     // Re-create the layers
292     create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
293 
294     // Free them again GrContext-style. This should free up everything.
295     cache.freeAll();
296 
297     REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
298 
299     REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));
300 
301 #if GR_CACHE_STATS
302     resourceCache->getStats(&stats);
303     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
304     REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
305 #endif
306 
307     // Purge the resource cache ...
308     resourceCache->purgeAllUnlocked();
309 
310 #if GR_CACHE_STATS
311     resourceCache->getStats(&stats);
312     REPORTER_ASSERT(reporter, 0 == stats.fTotal);
313 #endif
314 
315     // and try to re-attach to the backing texture. This should fail
316     cache.begin();
317     REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));
318 
319     //--------------------------------------------------------------------
320     // Test out the MessageBus-style purge. This will not free the atlas
321     // but should eliminate the free-floating layers.
322     create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
323 
324     // Allocate/use the layers
325     for (int i = 0; i < kInitialNumLayers; ++i) {
326         int key[1] = { i + 1 };
327         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
328                                                    key, 1);
329         REPORTER_ASSERT(reporter, layer);
330 
331         lock_layer(reporter, &cache, layer);
332     }
333 
334 #if GR_CACHE_STATS
335     resourceCache->getStats(&stats);
336     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
337     REPORTER_ASSERT(reporter, 2 == stats.fNumNonPurgeable);
338 #endif
339 
340     // Unlock the textures
341     for (int i = 0; i < kInitialNumLayers; ++i) {
342         int key[1] = { i+1 };
343 
344         GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
345                                                    key, 1);
346         REPORTER_ASSERT(reporter, layer);
347         cache.removeUse(layer);
348     }
349 
350     picture.reset(nullptr);
351     cache.processDeletedPictures();
352 
353     REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
354 
355 #if GR_CACHE_STATS
356     resourceCache->getStats(&stats);
357     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
358     REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
359     REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
360 #endif
361 
362     cache.end();
363 
364 #if GR_CACHE_STATS
365     resourceCache->getStats(&stats);
366     REPORTER_ASSERT(reporter, 2 == stats.fTotal);
367     REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
368 #endif
369 }
370 
371 #endif
372