2014-06-30 15:26:50 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2014 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if SK_SUPPORT_GPU
|
|
|
|
|
|
|
|
#include "GrContext.h"
|
|
|
|
#include "GrContextFactory.h"
|
|
|
|
#include "GrLayerCache.h"
|
2014-07-13 16:00:50 +00:00
|
|
|
#include "SkPictureRecorder.h"
|
2014-06-30 15:26:50 +00:00
|
|
|
#include "Test.h"
|
|
|
|
|
2014-07-22 17:18:06 +00:00
|
|
|
class TestingAccess {
|
2014-06-30 15:26:50 +00:00
|
|
|
public:
|
2015-08-19 16:51:00 +00:00
|
|
|
static int NumLayers(GrLayerCache* cache) {
|
2014-06-30 15:26:50 +00:00
|
|
|
return cache->numLayers();
|
|
|
|
}
|
2014-07-22 17:18:06 +00:00
|
|
|
static void Purge(GrLayerCache* cache, uint32_t pictureID) {
|
|
|
|
cache->purge(pictureID);
|
|
|
|
}
|
2014-10-10 18:38:29 +00:00
|
|
|
static int Uses(GrCachedLayer* layer) {
|
|
|
|
return layer->uses();
|
|
|
|
}
|
2014-12-01 17:09:27 +00:00
|
|
|
static GrCachedLayer* Find(GrLayerCache* cache, uint32_t pictureID,
|
2015-08-19 16:51:00 +00:00
|
|
|
const SkMatrix& initialMat,
|
|
|
|
const int* key, int keySize) {
|
2014-12-01 17:09:27 +00:00
|
|
|
return cache->findLayer(pictureID, initialMat, key, keySize);
|
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Add several layers to the cache
|
|
|
|
static void create_layers(skiatest::Reporter* reporter,
|
|
|
|
GrLayerCache* cache,
|
2014-07-29 13:07:19 +00:00
|
|
|
const SkPicture& picture,
|
2015-08-19 16:51:00 +00:00
|
|
|
int numToAdd,
|
|
|
|
int idOffset) {
|
2014-07-29 13:07:19 +00:00
|
|
|
|
2015-08-19 16:51:00 +00:00
|
|
|
for (int i = 0; i < numToAdd; ++i) {
|
|
|
|
int indices[1] = { idOffset+i+1 };
|
|
|
|
GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
|
|
|
|
idOffset+i+1, idOffset+i+2,
|
2014-10-20 15:52:40 +00:00
|
|
|
SkIRect::MakeEmpty(),
|
2014-12-16 16:25:55 +00:00
|
|
|
SkIRect::MakeEmpty(),
|
2014-09-17 14:50:47 +00:00
|
|
|
SkMatrix::I(),
|
2014-12-01 17:09:27 +00:00
|
|
|
indices, 1,
|
2015-08-27 14:41:13 +00:00
|
|
|
nullptr);
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2015-08-19 16:51:00 +00:00
|
|
|
GrCachedLayer* temp = TestingAccess::Find(cache, picture.uniqueID(), SkMatrix::I(),
|
2014-12-01 17:09:27 +00:00
|
|
|
indices, 1);
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, temp == layer);
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
|
2014-07-31 18:02:38 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
|
|
|
|
REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
|
2015-08-27 14:41:13 +00:00
|
|
|
REPORTER_ASSERT(reporter, nullptr == layer->texture());
|
|
|
|
REPORTER_ASSERT(reporter, nullptr == layer->paint());
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
|
|
|
}
|
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-29 13:07:19 +00:00
|
|
|
static void lock_layer(skiatest::Reporter* reporter,
|
|
|
|
GrLayerCache* cache,
|
|
|
|
GrCachedLayer* layer) {
|
|
|
|
// Make the layer 512x512 (so it can be atlased)
|
2014-10-28 21:33:06 +00:00
|
|
|
GrSurfaceDesc desc;
|
2014-07-29 13:07:19 +00:00
|
|
|
desc.fWidth = 512;
|
|
|
|
desc.fHeight = 512;
|
|
|
|
desc.fConfig = kSkia8888_GrPixelConfig;
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-10-28 14:21:44 +00:00
|
|
|
bool needsRerendering;
|
|
|
|
bool inAtlas = cache->tryToAtlas(layer, desc, &needsRerendering);
|
|
|
|
if (!inAtlas) {
|
|
|
|
cache->lock(layer, desc, &needsRerendering);
|
|
|
|
}
|
2014-08-18 15:50:03 +00:00
|
|
|
REPORTER_ASSERT(reporter, needsRerendering);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-10-28 14:21:44 +00:00
|
|
|
cache->lock(layer, desc, &needsRerendering);
|
2014-08-18 15:50:03 +00:00
|
|
|
REPORTER_ASSERT(reporter, !needsRerendering);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->texture());
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->locked());
|
2014-10-10 18:38:29 +00:00
|
|
|
|
|
|
|
cache->addUse(layer);
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, 1 == TestingAccess::Uses(layer));
|
2014-06-30 15:26:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// This test case exercises the public API of the GrLayerCache class.
|
|
|
|
// In particular it checks its interaction with the resource cache (w.r.t.
|
|
|
|
// locking & unlocking textures).
|
|
|
|
// TODO: need to add checks on VRAM usage!
|
|
|
|
DEF_GPUTEST(GpuLayerCache, reporter, factory) {
|
2015-08-19 16:51:00 +00:00
|
|
|
static const int kInitialNumLayers = 5;
|
2014-07-29 13:07:19 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
for (int i= 0; i < GrContextFactory::kGLContextTypeCnt; ++i) {
|
|
|
|
GrContextFactory::GLContextType glCtxType = (GrContextFactory::GLContextType) i;
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
if (!GrContextFactory::IsRenderingGLContext(glCtxType)) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
GrContext* context = factory->get(glCtxType);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2015-08-27 14:41:13 +00:00
|
|
|
if (nullptr == context) {
|
2014-07-17 17:50:59 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
SkPictureRecorder recorder;
|
2015-05-19 18:11:26 +00:00
|
|
|
SkCanvas* c = recorder.beginRecording(1, 1);
|
|
|
|
// Draw something, anything, to prevent an empty-picture optimization,
|
|
|
|
// which is a singleton and never purged.
|
|
|
|
c->drawRect(SkRect::MakeWH(1,1), SkPaint());
|
2014-07-17 17:50:59 +00:00
|
|
|
SkAutoTUnref<const SkPicture> picture(recorder.endRecording());
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
GrLayerCache cache(context);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-29 13:07:19 +00:00
|
|
|
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
|
2014-07-17 17:50:59 +00:00
|
|
|
|
2015-08-19 16:51:00 +00:00
|
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
|
|
int indices[1] = { i + 1 };
|
2014-12-01 17:09:27 +00:00
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
|
|
indices, 1);
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-29 13:07:19 +00:00
|
|
|
lock_layer(reporter, &cache, layer);
|
2014-07-17 17:50:59 +00:00
|
|
|
|
|
|
|
// The first 4 layers should be in the atlas (and thus have non-empty
|
|
|
|
// rects)
|
|
|
|
if (i < 4) {
|
|
|
|
REPORTER_ASSERT(reporter, layer->isAtlased());
|
|
|
|
} else {
|
2014-07-29 13:07:19 +00:00
|
|
|
// The 5th layer couldn't fit in the atlas
|
|
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
2014-07-17 17:50:59 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
// Unlock the textures
|
2015-08-19 16:51:00 +00:00
|
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
|
|
int indices[1] = { i+1 };
|
2014-12-01 17:09:27 +00:00
|
|
|
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
|
|
indices, 1);
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2014-10-10 18:38:29 +00:00
|
|
|
cache.removeUse(layer);
|
2014-07-17 17:50:59 +00:00
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2015-08-19 16:51:00 +00:00
|
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
|
|
int indices[1] = { i+1 };
|
2014-12-01 17:09:27 +00:00
|
|
|
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
|
|
indices, 1);
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-10-10 18:38:29 +00:00
|
|
|
// All the layers should be unlocked
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, !layer->locked());
|
2014-10-10 18:38:29 +00:00
|
|
|
|
2014-10-29 20:56:02 +00:00
|
|
|
// When hoisted layers aren't cached they are aggressively removed
|
|
|
|
// from the atlas
|
|
|
|
#if GR_CACHE_HOISTED_LAYERS
|
2014-07-29 13:07:19 +00:00
|
|
|
// The first 4 layers should still be in the atlas.
|
2014-07-17 17:50:59 +00:00
|
|
|
if (i < 4) {
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->texture());
|
2014-07-17 17:50:59 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->isAtlased());
|
|
|
|
} else {
|
2014-10-29 20:56:02 +00:00
|
|
|
#endif
|
2014-10-10 18:38:29 +00:00
|
|
|
// The final layer should not be atlased.
|
2015-08-27 14:41:13 +00:00
|
|
|
REPORTER_ASSERT(reporter, nullptr == layer->texture());
|
2014-07-17 17:50:59 +00:00
|
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
2014-10-29 20:56:02 +00:00
|
|
|
#if GR_CACHE_HOISTED_LAYERS
|
2014-07-17 17:50:59 +00:00
|
|
|
}
|
2014-10-29 20:56:02 +00:00
|
|
|
#endif
|
2014-07-17 17:50:59 +00:00
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-29 13:07:19 +00:00
|
|
|
{
|
2015-08-19 16:51:00 +00:00
|
|
|
int indices[1] = { kInitialNumLayers+1 };
|
2014-12-01 17:09:27 +00:00
|
|
|
|
2015-08-19 16:51:00 +00:00
|
|
|
// Add an additional layer. Since all the layers are unlocked this
|
2014-07-29 13:07:19 +00:00
|
|
|
// will force out the first atlased layer
|
|
|
|
create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
|
2014-12-01 17:09:27 +00:00
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
|
|
indices, 1);
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2014-07-29 13:07:19 +00:00
|
|
|
|
|
|
|
lock_layer(reporter, &cache, layer);
|
2014-10-10 18:38:29 +00:00
|
|
|
cache.removeUse(layer);
|
2014-07-29 13:07:19 +00:00
|
|
|
}
|
|
|
|
|
2015-08-19 16:51:00 +00:00
|
|
|
for (int i = 0; i < kInitialNumLayers+1; ++i) {
|
|
|
|
int indices[1] = { i+1 };
|
2014-12-01 17:09:27 +00:00
|
|
|
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
|
|
indices, 1);
|
2014-10-29 20:56:02 +00:00
|
|
|
#if GR_CACHE_HOISTED_LAYERS
|
2014-07-29 13:07:19 +00:00
|
|
|
// 3 old layers plus the new one should be in the atlas.
|
|
|
|
if (1 == i || 2 == i || 3 == i || 5 == i) {
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, !layer->locked());
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->texture());
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer->isAtlased());
|
|
|
|
} else if (4 == i) {
|
2014-10-29 20:56:02 +00:00
|
|
|
#endif
|
2014-07-29 13:07:19 +00:00
|
|
|
// The one that was never atlased should still be around
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, layer);
|
2014-07-29 13:07:19 +00:00
|
|
|
|
2015-08-27 14:41:13 +00:00
|
|
|
REPORTER_ASSERT(reporter, nullptr == layer->texture());
|
2014-07-29 13:07:19 +00:00
|
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
2014-10-29 20:56:02 +00:00
|
|
|
#if GR_CACHE_HOISTED_LAYERS
|
2014-07-29 13:07:19 +00:00
|
|
|
} else {
|
|
|
|
// The one bumped out of the atlas (i.e., 0) should be gone
|
2015-08-27 14:41:13 +00:00
|
|
|
REPORTER_ASSERT(reporter, nullptr == layer);
|
2014-07-29 13:07:19 +00:00
|
|
|
}
|
2014-10-29 20:56:02 +00:00
|
|
|
#endif
|
2014-07-29 13:07:19 +00:00
|
|
|
}
|
|
|
|
|
2014-07-22 17:18:06 +00:00
|
|
|
//--------------------------------------------------------------------
|
2014-07-17 17:50:59 +00:00
|
|
|
// Free them all SkGpuDevice-style. This will not free up the
|
|
|
|
// atlas' texture but will eliminate all the layers.
|
2014-07-22 17:18:06 +00:00
|
|
|
TestingAccess::Purge(&cache, picture->uniqueID());
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-22 17:18:06 +00:00
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
|
2014-07-17 17:50:59 +00:00
|
|
|
// TODO: add VRAM/resource cache check here
|
2014-07-22 17:18:06 +00:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
// Test out the GrContext-style purge. This should remove all the layers
|
|
|
|
// and the atlas.
|
2014-07-17 17:50:59 +00:00
|
|
|
// Re-create the layers
|
2014-07-29 13:07:19 +00:00
|
|
|
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-17 17:50:59 +00:00
|
|
|
// Free them again GrContext-style. This should free up everything.
|
|
|
|
cache.freeAll();
|
2014-06-30 15:26:50 +00:00
|
|
|
|
2014-07-22 17:18:06 +00:00
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
|
|
|
|
// TODO: add VRAM/resource cache check here
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
// Test out the MessageBus-style purge. This will not free the atlas
|
|
|
|
// but should eliminate the free-floating layers.
|
2014-07-29 13:07:19 +00:00
|
|
|
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
|
2014-07-22 17:18:06 +00:00
|
|
|
|
2015-08-27 14:41:13 +00:00
|
|
|
picture.reset(nullptr);
|
2014-07-22 17:18:06 +00:00
|
|
|
cache.processDeletedPictures();
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
|
2014-07-17 17:50:59 +00:00
|
|
|
// TODO: add VRAM/resource cache check here
|
|
|
|
}
|
2014-06-30 15:26:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|