c7ad40f76f
Most of this is (obviously) not necessary to do, but once I started, I figured I'd just get it all. Tools (nanobench, DM, skiaserve), all GMs, benches, and unit tests, plus support code (command line parsing and config stuff). This is almost entirely mechanical. Bug: skia: Change-Id: I209500f8df8c5bd43f8298ff26440d1c4d7425fb Reviewed-on: https://skia-review.googlesource.com/131153 Reviewed-by: Mike Klein <mtklein@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
372 lines
13 KiB
C++
372 lines
13 KiB
C++
/*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
// Disabling this test since it is for the layer hoister which is current disabled.
|
|
// The test fails when we add a discard to a newly created render target.
|
|
#if 0
|
|
|
|
#include "GrContext.h"
|
|
#include "GrLayerCache.h"
|
|
#include "GrResourceCache.h"
|
|
#include "SkPictureRecorder.h"
|
|
#include "Test.h"
|
|
|
|
class TestingAccess {
|
|
public:
|
|
static int NumPlots() {
|
|
return GrLayerCache::kNumPlotsX * GrLayerCache::kNumPlotsY;
|
|
}
|
|
static SkISize PlotSize() {
|
|
return SkISize::Make(GrLayerCache::kAtlasTextureWidth / GrLayerCache::kNumPlotsX,
|
|
GrLayerCache::kAtlasTextureHeight / GrLayerCache::kNumPlotsY);
|
|
}
|
|
|
|
static GrTexture* GetBackingTexture(GrLayerCache* cache) {
|
|
return cache->fAtlas->getTextureOrNull();
|
|
}
|
|
|
|
static int NumLayers(GrLayerCache* cache) {
|
|
return cache->numLayers();
|
|
}
|
|
static void Purge(GrLayerCache* cache, uint32_t pictureID) {
|
|
cache->purge(pictureID);
|
|
}
|
|
static int Uses(GrCachedLayer* layer) {
|
|
return layer->uses();
|
|
}
|
|
static GrCachedLayer* Find(GrLayerCache* cache, uint32_t pictureID,
|
|
const SkMatrix& initialMat,
|
|
const int* key, int keySize) {
|
|
return cache->findLayer(pictureID, initialMat, key, keySize);
|
|
}
|
|
};
|
|
|
|
// Add several layers to the cache
|
|
static void create_layers(skiatest::Reporter* reporter,
|
|
GrLayerCache* cache,
|
|
const SkPicture& picture,
|
|
int numToAdd,
|
|
int idOffset) {
|
|
|
|
for (int i = 0; i < numToAdd; ++i) {
|
|
int key[1] = { idOffset+i+1 };
|
|
GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
|
|
idOffset+i+1, idOffset+i+2,
|
|
SkIRect::MakeEmpty(),
|
|
SkIRect::MakeEmpty(),
|
|
SkMatrix::I(),
|
|
key, 1,
|
|
nullptr);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
GrCachedLayer* temp = TestingAccess::Find(cache, picture.uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, temp == layer);
|
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
|
|
|
|
REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
|
|
REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
|
|
REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
|
|
REPORTER_ASSERT(reporter, !layer->texture());
|
|
REPORTER_ASSERT(reporter, !layer->paint());
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
|
}
|
|
}
|
|
|
|
static void lock_layer(skiatest::Reporter* reporter,
|
|
GrLayerCache* cache,
|
|
GrCachedLayer* layer) {
|
|
// Make each layer big enough to consume one whole plot in the atlas
|
|
GrSurfaceDesc desc;
|
|
desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
|
desc.fWidth = TestingAccess::PlotSize().fWidth;
|
|
desc.fHeight = TestingAccess::PlotSize().fHeight;
|
|
desc.fConfig = kSkia8888_GrPixelConfig;
|
|
|
|
bool needsRerendering;
|
|
bool inAtlas = cache->tryToAtlas(layer, desc, &needsRerendering);
|
|
if (!inAtlas) {
|
|
cache->lock(layer, desc, &needsRerendering);
|
|
}
|
|
REPORTER_ASSERT(reporter, needsRerendering);
|
|
|
|
cache->lock(layer, desc, &needsRerendering);
|
|
REPORTER_ASSERT(reporter, !needsRerendering);
|
|
|
|
REPORTER_ASSERT(reporter, layer->texture());
|
|
REPORTER_ASSERT(reporter, layer->locked());
|
|
|
|
cache->addUse(layer);
|
|
|
|
REPORTER_ASSERT(reporter, 1 == TestingAccess::Uses(layer));
|
|
}
|
|
|
|
// 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_FOR_RENDERING_CONTEXTS(GpuLayerCache, reporter, ctxInfo) {
|
|
// Add one more layer than can fit in the atlas
|
|
static const int kInitialNumLayers = TestingAccess::NumPlots() + 1;
|
|
|
|
#if GR_CACHE_STATS
|
|
GrResourceCache::Stats stats;
|
|
#endif
|
|
|
|
sk_sp<SkPicture> picture;
|
|
|
|
{
|
|
SkPictureRecorder recorder;
|
|
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());
|
|
picture = recorder.finishRecordingAsPicture();
|
|
}
|
|
|
|
GrResourceCache* resourceCache = ctxInfo.grContext()->getResourceCache();
|
|
|
|
GrLayerCache cache(ctxInfo.grContext());
|
|
|
|
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
|
|
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
int key[1] = { i + 1 };
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
|
|
lock_layer(reporter, &cache, layer);
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
#endif
|
|
|
|
// The first 4 layers should be in the atlas (and thus have non-empty rects)
|
|
if (i < TestingAccess::NumPlots()) {
|
|
REPORTER_ASSERT(reporter, layer->isAtlased());
|
|
#if GR_CACHE_STATS
|
|
REPORTER_ASSERT(reporter, 1 == stats.fTotal);
|
|
#endif
|
|
} else {
|
|
// The 5th layer couldn't fit in the atlas
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
|
#if GR_CACHE_STATS
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Unlock the textures
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
int key[1] = { i+1 };
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
cache.removeUse(layer);
|
|
}
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
// The floating layer is purgeable the cache is not
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
|
|
#endif
|
|
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
int key[1] = { i+1 };
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
|
|
// All the layers should be unlocked
|
|
REPORTER_ASSERT(reporter, !layer->locked());
|
|
|
|
// When hoisted layers aren't cached they are aggressively removed
|
|
// from the atlas
|
|
#if GR_CACHE_HOISTED_LAYERS
|
|
// The first 4 layers should still be in the atlas.
|
|
if (i < 4) {
|
|
REPORTER_ASSERT(reporter, layer->texture());
|
|
REPORTER_ASSERT(reporter, layer->isAtlased());
|
|
} else {
|
|
#endif
|
|
// The final layer should not be atlased.
|
|
REPORTER_ASSERT(reporter, !layer->texture());
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
|
#if GR_CACHE_HOISTED_LAYERS
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// Let go of the backing texture
|
|
cache.end();
|
|
REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
// Now both the floater and the atlas are purgeable
|
|
REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
|
|
#endif
|
|
|
|
// re-attach to the backing texture
|
|
cache.begin();
|
|
REPORTER_ASSERT(reporter, TestingAccess::GetBackingTexture(&cache));
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
// The atlas is restored to being non-purgeable
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
|
|
#endif
|
|
|
|
{
|
|
int key[1] = { kInitialNumLayers+1 };
|
|
|
|
// Add an additional layer. Since all the layers are unlocked this
|
|
// will force out the first atlased layer
|
|
create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
|
|
lock_layer(reporter, &cache, layer);
|
|
cache.removeUse(layer);
|
|
}
|
|
|
|
for (int i = 0; i < kInitialNumLayers+1; ++i) {
|
|
int key[1] = { i+1 };
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
#if GR_CACHE_HOISTED_LAYERS
|
|
// 3 old layers plus the new one should be in the atlas.
|
|
if (1 == i || 2 == i || 3 == i || 5 == i) {
|
|
REPORTER_ASSERT(reporter, layer);
|
|
REPORTER_ASSERT(reporter, !layer->locked());
|
|
REPORTER_ASSERT(reporter, layer->texture());
|
|
REPORTER_ASSERT(reporter, layer->isAtlased());
|
|
} else if (4 == i) {
|
|
#endif
|
|
// The one that was never atlased should still be around
|
|
REPORTER_ASSERT(reporter, layer);
|
|
|
|
REPORTER_ASSERT(reporter, !layer->texture());
|
|
REPORTER_ASSERT(reporter, !layer->isAtlased());
|
|
#if GR_CACHE_HOISTED_LAYERS
|
|
} else {
|
|
// The one bumped out of the atlas (i.e., 0) should be gone
|
|
REPORTER_ASSERT(reporter, nullptr == layer);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Free them all SkGpuDevice-style. This will not free up the
|
|
// atlas' texture but will eliminate all the layers.
|
|
TestingAccess::Purge(&cache, picture->uniqueID());
|
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
// Atlas isn't purgeable
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
|
|
#endif
|
|
|
|
//--------------------------------------------------------------------
|
|
// Test out the GrContext-style purge. This should remove all the layers
|
|
// and the atlas.
|
|
// Re-create the layers
|
|
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
|
|
|
|
// Free them again GrContext-style. This should free up everything.
|
|
cache.freeAll();
|
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
|
|
|
|
REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
|
|
#endif
|
|
|
|
// Purge the resource cache ...
|
|
resourceCache->purgeAllUnlocked();
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 0 == stats.fTotal);
|
|
#endif
|
|
|
|
// and try to re-attach to the backing texture. This should fail
|
|
cache.begin();
|
|
REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));
|
|
|
|
//--------------------------------------------------------------------
|
|
// Test out the MessageBus-style purge. This will not free the atlas
|
|
// but should eliminate the free-floating layers.
|
|
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
|
|
|
|
// Allocate/use the layers
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
int key[1] = { i + 1 };
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
|
|
lock_layer(reporter, &cache, layer);
|
|
}
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fNumNonPurgeable);
|
|
#endif
|
|
|
|
// Unlock the textures
|
|
for (int i = 0; i < kInitialNumLayers; ++i) {
|
|
int key[1] = { i+1 };
|
|
|
|
GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
|
|
key, 1);
|
|
REPORTER_ASSERT(reporter, layer);
|
|
cache.removeUse(layer);
|
|
}
|
|
|
|
picture.reset(nullptr);
|
|
cache.processDeletedPictures();
|
|
|
|
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
|
|
REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
|
|
#endif
|
|
|
|
cache.end();
|
|
|
|
#if GR_CACHE_STATS
|
|
resourceCache->getStats(&stats);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fTotal);
|
|
REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
|
|
#endif
|
|
}
|
|
|
|
#endif
|