1cb93a386Sopenharmony_ci /* 2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkDiscardableMemory.h" 9cb93a386Sopenharmony_ci#include "src/core/SkResourceCache.h" 10cb93a386Sopenharmony_ci#include "tests/Test.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_cinamespace { 13cb93a386Sopenharmony_cistatic void* gGlobalAddress; 14cb93a386Sopenharmony_cistruct TestingKey : public SkResourceCache::Key { 15cb93a386Sopenharmony_ci intptr_t fValue; 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci TestingKey(intptr_t value, uint64_t sharedID = 0) : fValue(value) { 18cb93a386Sopenharmony_ci this->init(&gGlobalAddress, sharedID, sizeof(fValue)); 19cb93a386Sopenharmony_ci } 20cb93a386Sopenharmony_ci}; 21cb93a386Sopenharmony_cistruct TestingRec : public SkResourceCache::Rec { 22cb93a386Sopenharmony_ci TestingRec(const TestingKey& key, uint32_t value) : fKey(key), fValue(value) {} 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci TestingKey fKey; 25cb93a386Sopenharmony_ci intptr_t fValue; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci const Key& getKey() const override { return fKey; } 28cb93a386Sopenharmony_ci size_t bytesUsed() const override { return sizeof(fKey) + sizeof(fValue); } 29cb93a386Sopenharmony_ci const char* getCategory() const override { return "test_cache"; } 30cb93a386Sopenharmony_ci SkDiscardableMemory* diagnostic_only_getDiscardable() const override { return nullptr; } 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci static bool Visitor(const SkResourceCache::Rec& baseRec, void* context) { 33cb93a386Sopenharmony_ci const TestingRec& rec = static_cast<const TestingRec&>(baseRec); 34cb93a386Sopenharmony_ci intptr_t* result = (intptr_t*)context; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci *result = rec.fValue; 37cb93a386Sopenharmony_ci return true; 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci}; 40cb93a386Sopenharmony_ci} // namespace 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_cistatic const int COUNT = 10; 43cb93a386Sopenharmony_cistatic const int DIM = 256; 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_cistatic void test_cache(skiatest::Reporter* reporter, SkResourceCache& cache, bool testPurge) { 46cb93a386Sopenharmony_ci for (int i = 0; i < COUNT; ++i) { 47cb93a386Sopenharmony_ci TestingKey key(i); 48cb93a386Sopenharmony_ci intptr_t value = -1; 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value)); 51cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, -1 == value); 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci cache.add(new TestingRec(key, i)); 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value)); 56cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, i == value); 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci if (testPurge) { 60cb93a386Sopenharmony_ci // stress test, should trigger purges 61cb93a386Sopenharmony_ci for (int i = 0; i < COUNT * 100; ++i) { 62cb93a386Sopenharmony_ci TestingKey key(i); 63cb93a386Sopenharmony_ci cache.add(new TestingRec(key, i)); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci // test the originals after all that purging 68cb93a386Sopenharmony_ci for (int i = 0; i < COUNT; ++i) { 69cb93a386Sopenharmony_ci intptr_t value; 70cb93a386Sopenharmony_ci (void)cache.find(TestingKey(i), TestingRec::Visitor, &value); 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci cache.setTotalByteLimit(0); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_cistatic void test_cache_purge_shared_id(skiatest::Reporter* reporter, SkResourceCache& cache) { 77cb93a386Sopenharmony_ci for (int i = 0; i < COUNT; ++i) { 78cb93a386Sopenharmony_ci TestingKey key(i, i & 1); // every other key will have a 1 for its sharedID 79cb93a386Sopenharmony_ci cache.add(new TestingRec(key, i)); 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci // Ensure that everyone is present 83cb93a386Sopenharmony_ci for (int i = 0; i < COUNT; ++i) { 84cb93a386Sopenharmony_ci TestingKey key(i, i & 1); // every other key will have a 1 for its sharedID 85cb93a386Sopenharmony_ci intptr_t value = -1; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value)); 88cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, value == i); 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci // Now purge the ones that had a non-zero sharedID (the odd-indexed ones) 92cb93a386Sopenharmony_ci cache.purgeSharedID(1); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci // Ensure that only the even ones are still present 95cb93a386Sopenharmony_ci for (int i = 0; i < COUNT; ++i) { 96cb93a386Sopenharmony_ci TestingKey key(i, i & 1); // every other key will have a 1 for its sharedID 97cb93a386Sopenharmony_ci intptr_t value = -1; 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci if (i & 1) { 100cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value)); 101cb93a386Sopenharmony_ci } else { 102cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value)); 103cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, value == i); 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci#include "src/lazy/SkDiscardableMemoryPool.h" 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_cistatic SkDiscardableMemoryPool* gPool; 111cb93a386Sopenharmony_cistatic SkDiscardableMemory* pool_factory(size_t bytes) { 112cb93a386Sopenharmony_ci SkASSERT(gPool); 113cb93a386Sopenharmony_ci return gPool->create(bytes); 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ciDEF_TEST(ImageCache, reporter) { 117cb93a386Sopenharmony_ci static const size_t defLimit = DIM * DIM * 4 * COUNT + 1024; // 1K slop 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci { 120cb93a386Sopenharmony_ci SkResourceCache cache(defLimit); 121cb93a386Sopenharmony_ci test_cache(reporter, cache, true); 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci { 124cb93a386Sopenharmony_ci sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(defLimit)); 125cb93a386Sopenharmony_ci gPool = pool.get(); 126cb93a386Sopenharmony_ci SkResourceCache cache(pool_factory); 127cb93a386Sopenharmony_ci test_cache(reporter, cache, true); 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci { 130cb93a386Sopenharmony_ci SkResourceCache cache(SkDiscardableMemory::Create); 131cb93a386Sopenharmony_ci test_cache(reporter, cache, false); 132cb93a386Sopenharmony_ci } 133cb93a386Sopenharmony_ci { 134cb93a386Sopenharmony_ci SkResourceCache cache(defLimit); 135cb93a386Sopenharmony_ci test_cache_purge_shared_id(reporter, cache); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ciDEF_TEST(ImageCache_doubleAdd, r) { 140cb93a386Sopenharmony_ci // Adding the same key twice should be safe. 141cb93a386Sopenharmony_ci SkResourceCache cache(4096); 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci TestingKey key(1); 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci cache.add(new TestingRec(key, 2)); 146cb93a386Sopenharmony_ci cache.add(new TestingRec(key, 3)); 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci // Lookup can return either value. 149cb93a386Sopenharmony_ci intptr_t value = -1; 150cb93a386Sopenharmony_ci REPORTER_ASSERT(r, cache.find(key, TestingRec::Visitor, &value)); 151cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 2 == value || 3 == value); 152cb93a386Sopenharmony_ci} 153