Add mock context and use in ResourceCacheTest.

BUG=skia:2889

Committed: https://skia.googlesource.com/skia/+/820dd6c335411aad889c1d7e8a857642ecd87e30

Review URL: https://codereview.chromium.org/702083003
This commit is contained in:
bsalomon 2014-11-05 14:47:41 -08:00 committed by Commit bot
parent d5cd4ee5b8
commit 3343557421
4 changed files with 236 additions and 72 deletions

View File

@ -63,6 +63,11 @@ public:
*/
static GrContext* Create(GrBackend, GrBackendContext, const Options* opts = NULL);
/**
* Only defined in test apps.
*/
static GrContext* CreateMockContext();
virtual ~GrContext();
/**
@ -978,6 +983,8 @@ private:
GrContext(const Options&); // init must be called after the constructor.
bool init(GrBackend, GrBackendContext);
void initMockContext();
void initCommon();
void setupDrawBuffer();

View File

@ -121,7 +121,11 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
if (NULL == fGpu) {
return false;
}
this->initCommon();
return true;
}
void GrContext::initCommon() {
fDrawState = SkNEW(GrDrawState);
fGpu->setDrawState(fDrawState);
@ -141,8 +145,6 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
fDidTestPMConversions = false;
this->setupDrawBuffer();
return true;
}
GrContext::~GrContext() {
@ -156,14 +158,14 @@ GrContext::~GrContext() {
(*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
}
delete fResourceCache2;
SkDELETE(fResourceCache2);
fResourceCache2 = NULL;
delete fResourceCache;
SkDELETE(fResourceCache);
fResourceCache = NULL;
delete fFontCache;
delete fDrawBuffer;
delete fDrawBufferVBAllocPool;
delete fDrawBufferIBAllocPool;
SkDELETE(fFontCache);
SkDELETE(fDrawBuffer);
SkDELETE(fDrawBufferVBAllocPool);
SkDELETE(fDrawBufferIBAllocPool);
fAARectRenderer->unref();
fOvalRenderer->unref();

View File

@ -40,3 +40,138 @@ void GrContext::setMaxTextureSizeOverride(int maxTextureSizeOverride) {
void GrContext::purgeAllUnlockedResources() {
fResourceCache->purgeAllUnlocked();
}
///////////////////////////////////////////////////////////////////////////////
// Code for the mock context. It's built on a mock GrGpu class that does nothing.
////
#include "GrBufferAllocPool.h"
#include "GrInOrderDrawBuffer.h"
#include "GrGpu.h"
class MockGpu : public GrGpu {
public:
MockGpu(GrContext* context) : INHERITED(context) { fCaps.reset(SkNEW(GrDrawTargetCaps)); }
virtual ~MockGpu() { }
virtual bool canWriteTexturePixels(const GrTexture*,
GrPixelConfig srcConfig) const SK_OVERRIDE {
return true;
}
virtual bool readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
int left, int top,
int width, int height,
GrPixelConfig config,
size_t rowBytes) const SK_OVERRIDE { return false; }
virtual void buildProgramDesc(const GrOptDrawState&,
const GrProgramDesc::DescInfo&,
GrGpu::DrawType,
const GrDeviceCoordTexture* dstCopy,
GrProgramDesc* desc) SK_OVERRIDE { }
virtual void discard(GrRenderTarget*) SK_OVERRIDE { }
private:
virtual void onResetContext(uint32_t resetBits) { };
virtual GrTexture* onCreateTexture(const GrSurfaceDesc& desc,
const void* srcData,
size_t rowBytes) SK_OVERRIDE {
return NULL;
}
virtual GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
const void* srcData) SK_OVERRIDE {
return NULL;
}
virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&) SK_OVERRIDE {
return NULL;
}
virtual GrRenderTarget* onWrapBackendRenderTarget(
const GrBackendRenderTargetDesc&) SK_OVERRIDE {
return NULL;
}
virtual GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) SK_OVERRIDE {
return NULL;
}
virtual GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) SK_OVERRIDE {
return NULL;
}
virtual void onGpuClear(GrRenderTarget*, const SkIRect* rect, GrColor color,
bool canIgnoreRect) SK_OVERRIDE { }
virtual void onClearStencilClip(GrRenderTarget*,
const SkIRect& rect,
bool insideClip) SK_OVERRIDE { }
virtual void onGpuDraw(const DrawInfo&) SK_OVERRIDE { }
virtual bool onReadPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig,
void* buffer,
size_t rowBytes) SK_OVERRIDE {
return false;
}
virtual bool onWriteTexturePixels(GrTexture* texture,
int left, int top, int width, int height,
GrPixelConfig config, const void* buffer,
size_t rowBytes) SK_OVERRIDE {
return false;
}
virtual void onResolveRenderTarget(GrRenderTarget* target) SK_OVERRIDE {
return;
}
virtual bool createStencilBufferForRenderTarget(GrRenderTarget*, int width,
int height) SK_OVERRIDE {
return false;
}
virtual bool attachStencilBufferToRenderTarget(GrStencilBuffer*, GrRenderTarget*) SK_OVERRIDE {
return false;
}
virtual bool flushGraphicsState(DrawType,
const GrClipMaskManager::ScissorState&,
const GrDeviceCoordTexture* dstCopy) SK_OVERRIDE {
return false;
}
virtual void clearStencil(GrRenderTarget* target) SK_OVERRIDE { }
virtual void didAddGpuTraceMarker() SK_OVERRIDE { }
virtual void didRemoveGpuTraceMarker() SK_OVERRIDE { }
typedef GrGpu INHERITED;
};
GrContext* GrContext::CreateMockContext() {
GrContext* context = SkNEW_ARGS(GrContext, (Options()));
context->initMockContext();
return context;
}
void GrContext::initMockContext() {
SkASSERT(NULL == fGpu);
fGpu = SkNEW_ARGS(MockGpu, (this));
SkASSERT(fGpu);
this->initCommon();
// We delete these because we want to test the cache starting with zero resources. Also, none of
// these objects are required for any of tests that use this context. TODO: make stop allocating
// resources in the buffer pools.
SkDELETE(fDrawBuffer);
SkDELETE(fDrawBufferVBAllocPool);
SkDELETE(fDrawBufferIBAllocPool);
fDrawBuffer = NULL;
fDrawBufferVBAllocPool = NULL;
fDrawBufferIBAllocPool = NULL;
}

View File

@ -11,6 +11,7 @@
#include "GrContextFactory.h"
#include "GrGpu.h"
#include "GrResourceCache.h"
#include "GrResourceCache2.h"
#include "SkCanvas.h"
#include "SkSurface.h"
#include "Test.h"
@ -19,9 +20,7 @@ static const int gWidth = 640;
static const int gHeight = 480;
////////////////////////////////////////////////////////////////////////////////
static void test_cache(skiatest::Reporter* reporter,
GrContext* context,
SkCanvas* canvas) {
static void test_cache(skiatest::Reporter* reporter, GrContext* context, SkCanvas* canvas) {
const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);
SkBitmap src;
@ -71,12 +70,12 @@ public:
, fCache(NULL)
, fToDelete(NULL)
, fSize(size) {
++fAlive;
++fNumAlive;
this->registerWithCache();
}
~TestResource() {
--fAlive;
--fNumAlive;
if (fToDelete) {
// Breaks our little 2-element cycle below.
fToDelete->setDeleteWhenDestroyed(NULL, NULL);
@ -92,7 +91,7 @@ public:
size_t gpuMemorySize() const SK_OVERRIDE { return fSize; }
static int alive() { return fAlive; }
static int NumAlive() { return fNumAlive; }
void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource) {
fCache = cache;
@ -103,11 +102,11 @@ private:
GrResourceCache* fCache;
TestResource* fToDelete;
size_t fSize;
static int fAlive;
static int fNumAlive;
typedef GrGpuResource INHERITED;
};
int TestResource::fAlive = 0;
int TestResource::fNumAlive = 0;
static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* context) {
GrCacheID::Domain domain = GrCacheID::GenerateDomain();
@ -117,30 +116,33 @@ static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* cont
GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
GrResourceKey key(GrCacheID(domain, keyData), t, 0);
GrResourceCache cache(context->getGpu()->caps(), 5, 30000);
context->setResourceCacheLimits(5, 30000);
GrResourceCache* cache = context->getResourceCache();
cache->purgeAllUnlocked();
SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
// Add two resources with the same key that delete each other from the cache when destroyed.
TestResource* a = new TestResource(context->getGpu());
TestResource* b = new TestResource(context->getGpu());
cache.addResource(key, a);
cache.addResource(key, b);
cache->addResource(key, a);
cache->addResource(key, b);
// Circle back.
a->setDeleteWhenDestroyed(&cache, b);
b->setDeleteWhenDestroyed(&cache, a);
a->setDeleteWhenDestroyed(cache, b);
b->setDeleteWhenDestroyed(cache, a);
a->unref();
b->unref();
// Add a third independent resource also with the same key.
GrGpuResource* r = new TestResource(context->getGpu());
cache.addResource(key, r);
cache->addResource(key, r);
r->unref();
// Invalidate all three, all three should be purged and destroyed.
REPORTER_ASSERT(reporter, 3 == TestResource::alive());
REPORTER_ASSERT(reporter, 3 == TestResource::NumAlive());
const GrResourceInvalidatedMessage msg = { key };
SkMessageBus<GrResourceInvalidatedMessage>::Post(msg);
cache.purgeAsNeeded();
REPORTER_ASSERT(reporter, 0 == TestResource::alive());
cache->purgeAsNeeded();
REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
}
static void test_cache_delete_on_destruction(skiatest::Reporter* reporter,
@ -154,38 +156,44 @@ static void test_cache_delete_on_destruction(skiatest::Reporter* reporter,
GrResourceKey key(GrCacheID(domain, keyData), t, 0);
{
{
GrResourceCache cache(context->getGpu()->caps(), 3, 30000);
TestResource* a = new TestResource(context->getGpu());
TestResource* b = new TestResource(context->getGpu());
cache.addResource(key, a);
cache.addResource(key, b);
context->setResourceCacheLimits(3, 30000);
GrResourceCache* cache = context->getResourceCache();
cache->purgeAllUnlocked();
SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
a->setDeleteWhenDestroyed(&cache, b);
b->setDeleteWhenDestroyed(&cache, a);
a->unref();
b->unref();
REPORTER_ASSERT(reporter, 2 == TestResource::alive());
}
REPORTER_ASSERT(reporter, 0 == TestResource::alive());
}
{
GrResourceCache cache(context->getGpu()->caps(), 3, 30000);
TestResource* a = new TestResource(context->getGpu());
TestResource* b = new TestResource(context->getGpu());
cache.addResource(key, a);
cache.addResource(key, b);
cache->addResource(key, a);
cache->addResource(key, b);
a->setDeleteWhenDestroyed(&cache, b);
b->setDeleteWhenDestroyed(&cache, a);
a->setDeleteWhenDestroyed(cache, b);
b->setDeleteWhenDestroyed(cache, a);
a->unref();
b->unref();
REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive());
cache->purgeAllUnlocked();
REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
}
{
context->setResourceCacheLimits(3, 30000);
GrResourceCache* cache = context->getResourceCache();
cache->purgeAllUnlocked();
SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
TestResource* a = new TestResource(context->getGpu());
TestResource* b = new TestResource(context->getGpu());
cache->addResource(key, a);
cache->addResource(key, b);
a->setDeleteWhenDestroyed(cache, b);
b->setDeleteWhenDestroyed(cache, a);
a->unref();
b->unref();
cache.deleteResource(a->getCacheEntry());
cache->deleteResource(a->getCacheEntry());
REPORTER_ASSERT(reporter, 0 == TestResource::alive());
REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
}
}
@ -206,48 +214,54 @@ static void test_resource_size_changed(skiatest::Reporter* reporter,
// Test changing resources sizes (both increase & decrease).
{
GrResourceCache cache(context->getGpu()->caps(), 2, 300);
context->setResourceCacheLimits(3, 30000);
GrResourceCache* cache = context->getResourceCache();
cache->purgeAllUnlocked();
SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
TestResource* a = new TestResource(context->getGpu());
a->setSize(100); // Test didChangeGpuMemorySize() when not in the cache.
cache.addResource(key1, a);
cache->addResource(key1, a);
a->unref();
TestResource* b = new TestResource(context->getGpu());
b->setSize(100);
cache.addResource(key2, b);
cache->addResource(key2, b);
b->unref();
REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
REPORTER_ASSERT(reporter, 200 == cache->getCachedResourceBytes());
REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount());
static_cast<TestResource*>(cache.find(key2))->setSize(200);
static_cast<TestResource*>(cache.find(key1))->setSize(50);
static_cast<TestResource*>(cache->find(key2))->setSize(200);
static_cast<TestResource*>(cache->find(key1))->setSize(50);
REPORTER_ASSERT(reporter, 250 == cache.getCachedResourceBytes());
REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
REPORTER_ASSERT(reporter, 250 == cache->getCachedResourceBytes());
REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount());
}
// Test increasing a resources size beyond the cache budget.
{
GrResourceCache cache(context->getGpu()->caps(), 2, 300);
context->setResourceCacheLimits(2, 300);
GrResourceCache* cache = context->getResourceCache();
cache->purgeAllUnlocked();
SkASSERT(0 == cache->getCachedResourceCount() && 0 == cache->getCachedResourceBytes());
TestResource* a = new TestResource(context->getGpu(), 100);
cache.addResource(key1, a);
cache->addResource(key1, a);
a->unref();
TestResource* b = new TestResource(context->getGpu(), 100);
cache.addResource(key2, b);
cache->addResource(key2, b);
b->unref();
REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
REPORTER_ASSERT(reporter, 200 == cache->getCachedResourceBytes());
REPORTER_ASSERT(reporter, 2 == cache->getCachedResourceCount());
static_cast<TestResource*>(cache.find(key2))->setSize(201);
REPORTER_ASSERT(reporter, NULL == cache.find(key1));
static_cast<TestResource*>(cache->find(key2))->setSize(201);
REPORTER_ASSERT(reporter, !cache->hasKey(key1));
REPORTER_ASSERT(reporter, 201 == cache.getCachedResourceBytes());
REPORTER_ASSERT(reporter, 1 == cache.getCachedResourceCount());
REPORTER_ASSERT(reporter, 201 == cache->getCachedResourceBytes());
REPORTER_ASSERT(reporter, 1 == cache->getCachedResourceCount());
}
}
@ -262,7 +276,6 @@ DEF_GPUTEST(ResourceCache, reporter, factory) {
if (NULL == context) {
continue;
}
GrSurfaceDesc desc;
desc.fConfig = kSkia8888_GrPixelConfig;
desc.fFlags = kRenderTarget_GrSurfaceFlag;
@ -270,12 +283,19 @@ DEF_GPUTEST(ResourceCache, reporter, factory) {
desc.fHeight = gHeight;
SkImageInfo info = SkImageInfo::MakeN32Premul(gWidth, gHeight);
SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context, info));
test_cache(reporter, context, surface->getCanvas());
test_purge_invalidated(reporter, context);
test_cache_delete_on_destruction(reporter, context);
test_resource_size_changed(reporter, context);
}
// The below tests use a mock context.
SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
REPORTER_ASSERT(reporter, SkToBool(context));
if (NULL == context) {
return;
}
test_purge_invalidated(reporter, context);
test_cache_delete_on_destruction(reporter, context);
test_resource_size_changed(reporter, context);
}
#endif