blob: 8ca7b2bdfb18c6887fa99509fab6c5a0022bb818 [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:
18 static int NumLayers(GrLayerCache* cache) {
19 return cache->numLayers();
20 }
robertphillipsd771f6b2014-07-22 10:18:06 -070021 static void Purge(GrLayerCache* cache, uint32_t pictureID) {
22 cache->purge(pictureID);
23 }
robertphillips952841b2014-06-30 08:26:50 -070024};
25
26// Add several layers to the cache
27static void create_layers(skiatest::Reporter* reporter,
28 GrLayerCache* cache,
robertphillips320c9232014-07-29 06:07:19 -070029 const SkPicture& picture,
30 int numToAdd,
31 int idOffset) {
robertphillips952841b2014-06-30 08:26:50 -070032
robertphillips320c9232014-07-29 06:07:19 -070033 for (int i = 0; i < numToAdd; ++i) {
34 GrCachedLayer* layer = cache->findLayerOrCreate(&picture, idOffset+i);
35 REPORTER_ASSERT(reporter, NULL != layer);
36 GrCachedLayer* temp = cache->findLayer(&picture, idOffset+i);
37 REPORTER_ASSERT(reporter, temp == layer);
robertphillips952841b2014-06-30 08:26:50 -070038
robertphillips320c9232014-07-29 06:07:19 -070039 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
robertphillips952841b2014-06-30 08:26:50 -070040
robertphillips320c9232014-07-29 06:07:19 -070041 REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
42 REPORTER_ASSERT(reporter, layer->layerID() == idOffset + i);
43 REPORTER_ASSERT(reporter, NULL == layer->texture());
44 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips952841b2014-06-30 08:26:50 -070045 }
46
robertphillipsd771f6b2014-07-22 10:18:06 -070047 cache->trackPicture(&picture);
robertphillips952841b2014-06-30 08:26:50 -070048}
49
robertphillips320c9232014-07-29 06:07:19 -070050static void lock_layer(skiatest::Reporter* reporter,
51 GrLayerCache* cache,
52 GrCachedLayer* layer) {
53 // Make the layer 512x512 (so it can be atlased)
54 GrTextureDesc desc;
55 desc.fWidth = 512;
56 desc.fHeight = 512;
57 desc.fConfig = kSkia8888_GrPixelConfig;
58
59 bool foundInCache = cache->lock(layer, desc);
60 REPORTER_ASSERT(reporter, !foundInCache);
61
62 foundInCache = cache->lock(layer, desc);
63 REPORTER_ASSERT(reporter, foundInCache);
64
65 REPORTER_ASSERT(reporter, NULL != layer->texture());
66 REPORTER_ASSERT(reporter, layer->locked());
67}
68
robertphillips952841b2014-06-30 08:26:50 -070069// This test case exercises the public API of the GrLayerCache class.
70// In particular it checks its interaction with the resource cache (w.r.t.
71// locking & unlocking textures).
72// TODO: need to add checks on VRAM usage!
73DEF_GPUTEST(GpuLayerCache, reporter, factory) {
robertphillips320c9232014-07-29 06:07:19 -070074 static const int kInitialNumLayers = 5;
75
bsalomone904c092014-07-17 10:50:59 -070076 for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
77 GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
robertphillips952841b2014-06-30 08:26:50 -070078
bsalomone904c092014-07-17 10:50:59 -070079 if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
80 continue;
robertphillips952841b2014-06-30 08:26:50 -070081 }
robertphillips952841b2014-06-30 08:26:50 -070082
bsalomone904c092014-07-17 10:50:59 -070083 GrContext* context = factory->get(glCtxType);
robertphillips952841b2014-06-30 08:26:50 -070084
bsalomone904c092014-07-17 10:50:59 -070085 if (NULL == context) {
86 continue;
87 }
robertphillips952841b2014-06-30 08:26:50 -070088
bsalomone904c092014-07-17 10:50:59 -070089 SkPictureRecorder recorder;
90 recorder.beginRecording(1, 1);
91 SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
robertphillips952841b2014-06-30 08:26:50 -070092
bsalomone904c092014-07-17 10:50:59 -070093 GrLayerCache cache(context);
94
robertphillips320c9232014-07-29 06:07:19 -070095 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
bsalomone904c092014-07-17 10:50:59 -070096
robertphillips320c9232014-07-29 06:07:19 -070097 for (int i = 0; i < kInitialNumLayers; ++i) {
bsalomone904c092014-07-17 10:50:59 -070098 GrCachedLayer* layer = cache.findLayer(picture, i);
99 REPORTER_ASSERT(reporter, NULL != layer);
100
robertphillips320c9232014-07-29 06:07:19 -0700101 lock_layer(reporter, &cache, layer);
bsalomone904c092014-07-17 10:50:59 -0700102
bsalomone904c092014-07-17 10:50:59 -0700103 // The first 4 layers should be in the atlas (and thus have non-empty
104 // rects)
105 if (i < 4) {
106 REPORTER_ASSERT(reporter, layer->isAtlased());
107 } else {
robertphillips320c9232014-07-29 06:07:19 -0700108 // The 5th layer couldn't fit in the atlas
109 REPORTER_ASSERT(reporter, !layer->isAtlased());
bsalomone904c092014-07-17 10:50:59 -0700110 }
robertphillips952841b2014-06-30 08:26:50 -0700111 }
bsalomone904c092014-07-17 10:50:59 -0700112
113 // Unlock the textures
robertphillips320c9232014-07-29 06:07:19 -0700114 for (int i = 0; i < kInitialNumLayers; ++i) {
bsalomone904c092014-07-17 10:50:59 -0700115 GrCachedLayer* layer = cache.findLayer(picture, i);
116 REPORTER_ASSERT(reporter, NULL != layer);
117
118 cache.unlock(layer);
119 }
120
robertphillips320c9232014-07-29 06:07:19 -0700121 for (int i = 0; i < kInitialNumLayers; ++i) {
bsalomone904c092014-07-17 10:50:59 -0700122 GrCachedLayer* layer = cache.findLayer(picture, i);
123 REPORTER_ASSERT(reporter, NULL != layer);
124
robertphillips320c9232014-07-29 06:07:19 -0700125 REPORTER_ASSERT(reporter, !layer->locked());
robertphillips320c9232014-07-29 06:07:19 -0700126 // The first 4 layers should still be in the atlas.
bsalomone904c092014-07-17 10:50:59 -0700127 if (i < 4) {
128 REPORTER_ASSERT(reporter, NULL != layer->texture());
129 REPORTER_ASSERT(reporter, layer->isAtlased());
130 } else {
robertphillips320c9232014-07-29 06:07:19 -0700131 // The final layer should be unlocked.
bsalomone904c092014-07-17 10:50:59 -0700132 REPORTER_ASSERT(reporter, NULL == layer->texture());
133 REPORTER_ASSERT(reporter, !layer->isAtlased());
bsalomone904c092014-07-17 10:50:59 -0700134 }
bsalomone904c092014-07-17 10:50:59 -0700135 }
136
robertphillips320c9232014-07-29 06:07:19 -0700137 {
138 // Add an additional layer. Since all the layers are unlocked this
139 // will force out the first atlased layer
140 create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
141 GrCachedLayer* layer = cache.findLayer(picture, kInitialNumLayers);
142 REPORTER_ASSERT(reporter, NULL != layer);
143
144 lock_layer(reporter, &cache, layer);
145 cache.unlock(layer);
146 }
147
148 for (int i = 0; i < kInitialNumLayers+1; ++i) {
149 GrCachedLayer* layer = cache.findLayer(picture, i);
robertphillips320c9232014-07-29 06:07:19 -0700150 // 3 old layers plus the new one should be in the atlas.
151 if (1 == i || 2 == i || 3 == i || 5 == i) {
152 REPORTER_ASSERT(reporter, NULL != layer);
153 REPORTER_ASSERT(reporter, !layer->locked());
154 REPORTER_ASSERT(reporter, NULL != layer->texture());
155 REPORTER_ASSERT(reporter, layer->isAtlased());
156 } else if (4 == i) {
robertphillips320c9232014-07-29 06:07:19 -0700157 // The one that was never atlased should still be around
158 REPORTER_ASSERT(reporter, NULL != layer);
159
160 REPORTER_ASSERT(reporter, NULL == layer->texture());
161 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips320c9232014-07-29 06:07:19 -0700162 } else {
163 // The one bumped out of the atlas (i.e., 0) should be gone
164 REPORTER_ASSERT(reporter, NULL == layer);
165 }
robertphillips320c9232014-07-29 06:07:19 -0700166 }
167
robertphillipsd771f6b2014-07-22 10:18:06 -0700168 //--------------------------------------------------------------------
bsalomone904c092014-07-17 10:50:59 -0700169 // Free them all SkGpuDevice-style. This will not free up the
170 // atlas' texture but will eliminate all the layers.
robertphillipsd771f6b2014-07-22 10:18:06 -0700171 TestingAccess::Purge(&cache, picture->uniqueID());
bsalomone904c092014-07-17 10:50:59 -0700172
robertphillipsd771f6b2014-07-22 10:18:06 -0700173 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
bsalomone904c092014-07-17 10:50:59 -0700174 // TODO: add VRAM/resource cache check here
robertphillipsd771f6b2014-07-22 10:18:06 -0700175
176 //--------------------------------------------------------------------
177 // Test out the GrContext-style purge. This should remove all the layers
178 // and the atlas.
bsalomone904c092014-07-17 10:50:59 -0700179 // Re-create the layers
robertphillips320c9232014-07-29 06:07:19 -0700180 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
bsalomone904c092014-07-17 10:50:59 -0700181
182 // Free them again GrContext-style. This should free up everything.
183 cache.freeAll();
184
robertphillipsd771f6b2014-07-22 10:18:06 -0700185 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
bsalomone904c092014-07-17 10:50:59 -0700186 // TODO: add VRAM/resource cache check here
robertphillipsd771f6b2014-07-22 10:18:06 -0700187
188 //--------------------------------------------------------------------
189 // Test out the MessageBus-style purge. This will not free the atlas
190 // but should eliminate the free-floating layers.
robertphillips320c9232014-07-29 06:07:19 -0700191 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
robertphillipsd771f6b2014-07-22 10:18:06 -0700192
193 picture.reset(NULL);
194 cache.processDeletedPictures();
195
196 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
197 // TODO: add VRAM/resource cache check here
robertphillips952841b2014-06-30 08:26:50 -0700198 }
robertphillips952841b2014-06-30 08:26:50 -0700199}
200
201#endif