blob: 9e070564214a38a21527cff4ad9d411cfe9216df [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) {
robertphillips6f294af2014-08-18 08:50:03 -070034 GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
robertphillips0c423322014-07-31 11:02:38 -070035 idOffset+i+1, idOffset+i+2,
robertphillips4aa6dfc2014-09-17 07:50:47 -070036 SkMatrix::I(),
37 NULL);
bsalomon49f085d2014-09-05 13:34:00 -070038 REPORTER_ASSERT(reporter, layer);
robertphillipsed420592014-09-29 11:39:38 -070039 GrCachedLayer* temp = cache->findLayer(picture.uniqueID(), idOffset+i+1,
40 SkMatrix::I());
robertphillips320c9232014-07-29 06:07:19 -070041 REPORTER_ASSERT(reporter, temp == layer);
robertphillips952841b2014-06-30 08:26:50 -070042
robertphillips320c9232014-07-29 06:07:19 -070043 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
robertphillips952841b2014-06-30 08:26:50 -070044
robertphillips320c9232014-07-29 06:07:19 -070045 REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
robertphillips0c423322014-07-31 11:02:38 -070046 REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
47 REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
robertphillips320c9232014-07-29 06:07:19 -070048 REPORTER_ASSERT(reporter, NULL == layer->texture());
robertphillips4aa6dfc2014-09-17 07:50:47 -070049 REPORTER_ASSERT(reporter, NULL == layer->paint());
robertphillips320c9232014-07-29 06:07:19 -070050 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips952841b2014-06-30 08:26:50 -070051 }
52
robertphillipsd771f6b2014-07-22 10:18:06 -070053 cache->trackPicture(&picture);
robertphillips952841b2014-06-30 08:26:50 -070054}
55
robertphillips320c9232014-07-29 06:07:19 -070056static void lock_layer(skiatest::Reporter* reporter,
57 GrLayerCache* cache,
58 GrCachedLayer* layer) {
59 // Make the layer 512x512 (so it can be atlased)
60 GrTextureDesc desc;
61 desc.fWidth = 512;
62 desc.fHeight = 512;
63 desc.fConfig = kSkia8888_GrPixelConfig;
64
robertphillips6f294af2014-08-18 08:50:03 -070065 bool needsRerendering = cache->lock(layer, desc, false);
66 REPORTER_ASSERT(reporter, needsRerendering);
robertphillips320c9232014-07-29 06:07:19 -070067
robertphillips6f294af2014-08-18 08:50:03 -070068 needsRerendering = cache->lock(layer, desc, false);
69 REPORTER_ASSERT(reporter, !needsRerendering);
robertphillips320c9232014-07-29 06:07:19 -070070
bsalomon49f085d2014-09-05 13:34:00 -070071 REPORTER_ASSERT(reporter, layer->texture());
robertphillips320c9232014-07-29 06:07:19 -070072 REPORTER_ASSERT(reporter, layer->locked());
73}
74
robertphillips952841b2014-06-30 08:26:50 -070075// This test case exercises the public API of the GrLayerCache class.
76// In particular it checks its interaction with the resource cache (w.r.t.
77// locking & unlocking textures).
78// TODO: need to add checks on VRAM usage!
79DEF_GPUTEST(GpuLayerCache, reporter, factory) {
robertphillips320c9232014-07-29 06:07:19 -070080 static const int kInitialNumLayers = 5;
81
bsalomone904c092014-07-17 10:50:59 -070082 for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
83 GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
robertphillips952841b2014-06-30 08:26:50 -070084
bsalomone904c092014-07-17 10:50:59 -070085 if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
86 continue;
robertphillips952841b2014-06-30 08:26:50 -070087 }
robertphillips952841b2014-06-30 08:26:50 -070088
bsalomone904c092014-07-17 10:50:59 -070089 GrContext* context = factory->get(glCtxType);
robertphillips952841b2014-06-30 08:26:50 -070090
bsalomone904c092014-07-17 10:50:59 -070091 if (NULL == context) {
92 continue;
93 }
robertphillips952841b2014-06-30 08:26:50 -070094
bsalomone904c092014-07-17 10:50:59 -070095 SkPictureRecorder recorder;
96 recorder.beginRecording(1, 1);
97 SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
robertphillips952841b2014-06-30 08:26:50 -070098
bsalomone904c092014-07-17 10:50:59 -070099 GrLayerCache cache(context);
100
robertphillips320c9232014-07-29 06:07:19 -0700101 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
bsalomone904c092014-07-17 10:50:59 -0700102
robertphillips320c9232014-07-29 06:07:19 -0700103 for (int i = 0; i < kInitialNumLayers; ++i) {
robertphillipsed420592014-09-29 11:39:38 -0700104 GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, SkMatrix::I());
bsalomon49f085d2014-09-05 13:34:00 -0700105 REPORTER_ASSERT(reporter, layer);
bsalomone904c092014-07-17 10:50:59 -0700106
robertphillips320c9232014-07-29 06:07:19 -0700107 lock_layer(reporter, &cache, layer);
bsalomone904c092014-07-17 10:50:59 -0700108
bsalomone904c092014-07-17 10:50:59 -0700109 // The first 4 layers should be in the atlas (and thus have non-empty
110 // rects)
111 if (i < 4) {
112 REPORTER_ASSERT(reporter, layer->isAtlased());
113 } else {
robertphillips320c9232014-07-29 06:07:19 -0700114 // The 5th layer couldn't fit in the atlas
115 REPORTER_ASSERT(reporter, !layer->isAtlased());
bsalomone904c092014-07-17 10:50:59 -0700116 }
robertphillips952841b2014-06-30 08:26:50 -0700117 }
bsalomone904c092014-07-17 10:50:59 -0700118
119 // Unlock the textures
robertphillips320c9232014-07-29 06:07:19 -0700120 for (int i = 0; i < kInitialNumLayers; ++i) {
robertphillipsed420592014-09-29 11:39:38 -0700121 GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, SkMatrix::I());
bsalomon49f085d2014-09-05 13:34:00 -0700122 REPORTER_ASSERT(reporter, layer);
bsalomone904c092014-07-17 10:50:59 -0700123 cache.unlock(layer);
124 }
125
robertphillips320c9232014-07-29 06:07:19 -0700126 for (int i = 0; i < kInitialNumLayers; ++i) {
robertphillipsed420592014-09-29 11:39:38 -0700127 GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, SkMatrix::I());
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 REPORTER_ASSERT(reporter, !layer->locked());
robertphillips320c9232014-07-29 06:07:19 -0700131 // The first 4 layers should still be in the atlas.
bsalomone904c092014-07-17 10:50:59 -0700132 if (i < 4) {
bsalomon49f085d2014-09-05 13:34:00 -0700133 REPORTER_ASSERT(reporter, layer->texture());
bsalomone904c092014-07-17 10:50:59 -0700134 REPORTER_ASSERT(reporter, layer->isAtlased());
135 } else {
robertphillips320c9232014-07-29 06:07:19 -0700136 // The final layer should be unlocked.
bsalomone904c092014-07-17 10:50:59 -0700137 REPORTER_ASSERT(reporter, NULL == layer->texture());
138 REPORTER_ASSERT(reporter, !layer->isAtlased());
bsalomone904c092014-07-17 10:50:59 -0700139 }
bsalomone904c092014-07-17 10:50:59 -0700140 }
141
robertphillips320c9232014-07-29 06:07:19 -0700142 {
143 // Add an additional layer. Since all the layers are unlocked this
144 // will force out the first atlased layer
145 create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
robertphillips6f294af2014-08-18 08:50:03 -0700146 GrCachedLayer* layer = cache.findLayer(picture->uniqueID(),
robertphillipsed420592014-09-29 11:39:38 -0700147 kInitialNumLayers+1, SkMatrix::I());
bsalomon49f085d2014-09-05 13:34:00 -0700148 REPORTER_ASSERT(reporter, layer);
robertphillips320c9232014-07-29 06:07:19 -0700149
150 lock_layer(reporter, &cache, layer);
151 cache.unlock(layer);
152 }
153
154 for (int i = 0; i < kInitialNumLayers+1; ++i) {
robertphillipsed420592014-09-29 11:39:38 -0700155 GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, SkMatrix::I());
robertphillips320c9232014-07-29 06:07:19 -0700156 // 3 old layers plus the new one should be in the atlas.
157 if (1 == i || 2 == i || 3 == i || 5 == i) {
bsalomon49f085d2014-09-05 13:34:00 -0700158 REPORTER_ASSERT(reporter, layer);
robertphillips320c9232014-07-29 06:07:19 -0700159 REPORTER_ASSERT(reporter, !layer->locked());
bsalomon49f085d2014-09-05 13:34:00 -0700160 REPORTER_ASSERT(reporter, layer->texture());
robertphillips320c9232014-07-29 06:07:19 -0700161 REPORTER_ASSERT(reporter, layer->isAtlased());
162 } else if (4 == i) {
robertphillips320c9232014-07-29 06:07:19 -0700163 // The one that was never atlased should still be around
bsalomon49f085d2014-09-05 13:34:00 -0700164 REPORTER_ASSERT(reporter, layer);
robertphillips320c9232014-07-29 06:07:19 -0700165
166 REPORTER_ASSERT(reporter, NULL == layer->texture());
167 REPORTER_ASSERT(reporter, !layer->isAtlased());
robertphillips320c9232014-07-29 06:07:19 -0700168 } else {
169 // The one bumped out of the atlas (i.e., 0) should be gone
170 REPORTER_ASSERT(reporter, NULL == layer);
171 }
robertphillips320c9232014-07-29 06:07:19 -0700172 }
173
robertphillipsd771f6b2014-07-22 10:18:06 -0700174 //--------------------------------------------------------------------
bsalomone904c092014-07-17 10:50:59 -0700175 // Free them all SkGpuDevice-style. This will not free up the
176 // atlas' texture but will eliminate all the layers.
robertphillipsd771f6b2014-07-22 10:18:06 -0700177 TestingAccess::Purge(&cache, picture->uniqueID());
bsalomone904c092014-07-17 10:50:59 -0700178
robertphillipsd771f6b2014-07-22 10:18:06 -0700179 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
bsalomone904c092014-07-17 10:50:59 -0700180 // TODO: add VRAM/resource cache check here
robertphillipsd771f6b2014-07-22 10:18:06 -0700181
182 //--------------------------------------------------------------------
183 // Test out the GrContext-style purge. This should remove all the layers
184 // and the atlas.
bsalomone904c092014-07-17 10:50:59 -0700185 // Re-create the layers
robertphillips320c9232014-07-29 06:07:19 -0700186 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
bsalomone904c092014-07-17 10:50:59 -0700187
188 // Free them again GrContext-style. This should free up everything.
189 cache.freeAll();
190
robertphillipsd771f6b2014-07-22 10:18:06 -0700191 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
bsalomone904c092014-07-17 10:50:59 -0700192 // TODO: add VRAM/resource cache check here
robertphillipsd771f6b2014-07-22 10:18:06 -0700193
194 //--------------------------------------------------------------------
195 // Test out the MessageBus-style purge. This will not free the atlas
196 // but should eliminate the free-floating layers.
robertphillips320c9232014-07-29 06:07:19 -0700197 create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
robertphillipsd771f6b2014-07-22 10:18:06 -0700198
199 picture.reset(NULL);
200 cache.processDeletedPictures();
201
202 REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
203 // TODO: add VRAM/resource cache check here
robertphillips952841b2014-06-30 08:26:50 -0700204 }
robertphillips952841b2014-06-30 08:26:50 -0700205}
206
207#endif