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