1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 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 "include/core/SkRefCnt.h" 9cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 10cb93a386Sopenharmony_ci#include "include/private/SkMalloc.h" 11cb93a386Sopenharmony_ci#include "src/core/SkCachedData.h" 12cb93a386Sopenharmony_ci#include "src/lazy/SkDiscardableMemoryPool.h" 13cb93a386Sopenharmony_ci#include "tests/Test.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include <cstring> 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ciclass SkDiscardableMemory; 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cienum LockedState { 20cb93a386Sopenharmony_ci kUnlocked, 21cb93a386Sopenharmony_ci kLocked, 22cb93a386Sopenharmony_ci}; 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cienum CachedState { 25cb93a386Sopenharmony_ci kNotInCache, 26cb93a386Sopenharmony_ci kInCache, 27cb93a386Sopenharmony_ci}; 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_cistatic void check_data(skiatest::Reporter* reporter, SkCachedData* data, 30cb93a386Sopenharmony_ci int refcnt, CachedState cacheState, LockedState lockedState) { 31cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt); 32cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState)); 33cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, data->testing_only_isLocked() == (lockedState == kLocked)); 34cb93a386Sopenharmony_ci} 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_cistatic SkCachedData* make_data(size_t size, SkDiscardableMemoryPool* pool) { 37cb93a386Sopenharmony_ci if (pool) { 38cb93a386Sopenharmony_ci SkDiscardableMemory* dm = pool->create(size); 39cb93a386Sopenharmony_ci // the pool "can" return null, but it shouldn't in these controlled conditions 40cb93a386Sopenharmony_ci SkASSERT_RELEASE(dm); 41cb93a386Sopenharmony_ci return new SkCachedData(size, dm); 42cb93a386Sopenharmony_ci } else { 43cb93a386Sopenharmony_ci return new SkCachedData(sk_malloc_throw(size), size); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci} 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci// returns with the data locked by client and cache 48cb93a386Sopenharmony_cistatic SkCachedData* test_locking(skiatest::Reporter* reporter, 49cb93a386Sopenharmony_ci size_t size, SkDiscardableMemoryPool* pool) { 50cb93a386Sopenharmony_ci SkCachedData* data = make_data(size, pool); 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci memset(data->writable_data(), 0x80, size); // just to use writable_data() 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci check_data(reporter, data, 1, kNotInCache, kLocked); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci data->ref(); 57cb93a386Sopenharmony_ci check_data(reporter, data, 2, kNotInCache, kLocked); 58cb93a386Sopenharmony_ci data->unref(); 59cb93a386Sopenharmony_ci check_data(reporter, data, 1, kNotInCache, kLocked); 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci data->attachToCacheAndRef(); 62cb93a386Sopenharmony_ci check_data(reporter, data, 2, kInCache, kLocked); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci data->unref(); 65cb93a386Sopenharmony_ci check_data(reporter, data, 1, kInCache, kUnlocked); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci data->ref(); 68cb93a386Sopenharmony_ci check_data(reporter, data, 2, kInCache, kLocked); 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci return data; 71cb93a386Sopenharmony_ci} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci/* 74cb93a386Sopenharmony_ci * SkCachedData behaves differently (regarding its locked/unlocked state) depending on 75cb93a386Sopenharmony_ci * when it is in the cache or not. Being in the cache is signaled by calling attachToCacheAndRef() 76cb93a386Sopenharmony_ci * instead of ref(). (and balanced by detachFromCacheAndUnref). 77cb93a386Sopenharmony_ci * 78cb93a386Sopenharmony_ci * Thus, among other things, we test the end-of-life behavior when the client is the last owner 79cb93a386Sopenharmony_ci * and when the cache is. 80cb93a386Sopenharmony_ci */ 81cb93a386Sopenharmony_ciDEF_TEST(CachedData, reporter) { 82cb93a386Sopenharmony_ci sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(1000)); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) { 85cb93a386Sopenharmony_ci const size_t size = 100; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci // test with client as last owner 88cb93a386Sopenharmony_ci SkCachedData* data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr); 89cb93a386Sopenharmony_ci check_data(reporter, data, 2, kInCache, kLocked); 90cb93a386Sopenharmony_ci data->detachFromCacheAndUnref(); 91cb93a386Sopenharmony_ci check_data(reporter, data, 1, kNotInCache, kLocked); 92cb93a386Sopenharmony_ci data->unref(); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci // test with cache as last owner 95cb93a386Sopenharmony_ci data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr); 96cb93a386Sopenharmony_ci check_data(reporter, data, 2, kInCache, kLocked); 97cb93a386Sopenharmony_ci data->unref(); 98cb93a386Sopenharmony_ci check_data(reporter, data, 1, kInCache, kUnlocked); 99cb93a386Sopenharmony_ci data->detachFromCacheAndUnref(); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci} 102