'tools.gyp:picture_utils',
'tools.gyp:resources',
'tools.gyp:sk_tool_utils',
+ 'tools.gyp:ref_cnt_is',
],
'sources': [
'../tests/Test.cpp',
],
],
},
+ {
+ 'target_name': 'ref_cnt_is',
+ 'type': 'static_library',
+ 'sources': [ '../tools/RefCntIs.cpp' ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [ '../tools' ],
+ },
+ 'dependencies': [
+ 'skia_lib.gyp:skia_lib',
+ ],
+ },
{ # This would go in gm.gyp, but it's also used by skimage below.
'target_name': 'gm_expectations',
'type': 'static_library',
class SK_API Cache : public SkRefCnt {
public:
// By default, we cache only image filters with 2 or more children.
+ // Values less than 2 mean always cache; values greater than 2 are not supported.
static Cache* Create(int minChildren = 2);
virtual ~Cache() {}
virtual bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) = 0;
#endif
}
+#ifdef SK_DEBUG
/** Return the reference count. Use only for debugging. */
int32_t getRefCnt() const { return fRefCnt; }
+#endif
/** May return true if the caller is the only owner.
* Ensures that all previous owner's actions are complete.
mutable int32_t fRefCnt;
+ // Used by tests.
+ friend bool RefCntIs(const SkRefCntBase&, int32_t);
+
typedef SkNoncopyable INHERITED;
};
*/
SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}
+#ifdef SK_DEBUG
/** Destruct, asserting that the weak reference count is 1.
*/
virtual ~SkWeakRefCnt() {
-#ifdef SK_DEBUG
SkASSERT(fWeakCnt == 1);
fWeakCnt = 0;
-#endif
}
/** Return the weak reference count.
*/
int32_t getWeakCnt() const { return fWeakCnt; }
-#ifdef SK_DEBUG
void validate() const {
this->INHERITED::validate();
SkASSERT(fWeakCnt > 0);
/* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */
mutable int32_t fWeakCnt;
+ // Used by tests.
+ friend bool WeakRefCntIs(const SkWeakRefCnt&, int32_t);
+
typedef SkRefCnt INHERITED;
};
class CacheImpl : public SkImageFilter::Cache {
public:
- explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {}
+ explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {
+ SkASSERT(fMinChildren <= 2);
+ }
+
virtual ~CacheImpl();
bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
void set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) SK_OVERRIDE;
}
void CacheImpl::set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) {
- if (key->getRefCnt() >= fMinChildren) {
+ if (fMinChildren < 2 || !key->unique()) {
+ // We take !key->unique() as a signal that there are probably at least 2 refs on the key,
+ // meaning this filter probably has at least two children and is worth caching when
+ // fMinChildren is 2. If fMinChildren is less than two, we'll just always cache.
fData.add(new Value(key, result, offset));
}
}
*/
#include "Test.h"
+#include "RefCntIs.h"
// This is a GR test
#if SK_SUPPORT_GPU
#include "../../src/gpu/GrClipMaskManager.h"
// check that the set took
check_state(reporter, cache, clip1, texture1, bound1);
- REPORTER_ASSERT(reporter, texture1->getRefCnt());
+ REPORTER_ASSERT(reporter, !RefCntIs(*texture1, 0));
// push the state
cache.push();
// verify that the pushed state is initially empty
check_empty_state(reporter, cache);
- REPORTER_ASSERT(reporter, texture1->getRefCnt());
+ REPORTER_ASSERT(reporter, !RefCntIs(*texture1, 0));
// modify the new state
SkIRect bound2;
// check that the changes took
check_state(reporter, cache, clip2, texture2, bound2);
- REPORTER_ASSERT(reporter, texture1->getRefCnt());
- REPORTER_ASSERT(reporter, texture2->getRefCnt());
+ REPORTER_ASSERT(reporter, !RefCntIs(*texture1, 0));
+ REPORTER_ASSERT(reporter, !RefCntIs(*texture2, 0));
// check to make sure canReuse works
REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2));
// verify that the old state is restored
check_state(reporter, cache, clip1, texture1, bound1);
- REPORTER_ASSERT(reporter, texture1->getRefCnt());
+ REPORTER_ASSERT(reporter, !RefCntIs(*texture1, 0));
// manually clear the state
cache.reset();
SkIPoint offset;
SkString str;
str.printf("filter %d", static_cast<int>(i));
- SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create(2));
+ SkAutoTUnref<SkImageFilter::Cache> cache(SkImageFilter::Cache::Create());
SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), cache.get());
REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx,
&result, &offset), str.c_str());
*/
#include "SkMetaData.h"
+#include "RefCntIs.h"
#include "Test.h"
static void test_ptrs(skiatest::Reporter* reporter) {
SkRefCnt ref;
- REPORTER_ASSERT(reporter, 1 == ref.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(ref, 1));
{
SkMetaData md0, md1;
md0.setRefCnt(name, &ref);
REPORTER_ASSERT(reporter, md0.findRefCnt(name));
REPORTER_ASSERT(reporter, md0.hasRefCnt(name, &ref));
- REPORTER_ASSERT(reporter, 2 == ref.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(ref, 2));
md1 = md0;
REPORTER_ASSERT(reporter, md1.findRefCnt(name));
REPORTER_ASSERT(reporter, md1.hasRefCnt(name, &ref));
- REPORTER_ASSERT(reporter, 3 == ref.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(ref, 3));
REPORTER_ASSERT(reporter, md0.removeRefCnt(name));
REPORTER_ASSERT(reporter, !md0.findRefCnt(name));
REPORTER_ASSERT(reporter, !md0.hasRefCnt(name, &ref));
- REPORTER_ASSERT(reporter, 2 == ref.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(ref, 2));
}
- REPORTER_ASSERT(reporter, 1 == ref.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(ref, 1));
}
DEF_TEST(MetaData, reporter) {
#include "SkThreadUtils.h"
#include "SkTypes.h"
#include "SkWeakRefCnt.h"
+#include "RefCntIs.h"
#include "Test.h"
class InstCounterClass {
const int N = 10;
SkTRefArray<InstCounterClass>* array = SkTRefArray<InstCounterClass>::Create(N);
- REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(*array, 1));
REPORTER_ASSERT(reporter, N == array->count());
REPORTER_ASSERT(reporter, N == InstCounterClass::gInstCounter);
}
array = SkTRefArray<InstCounterClass>::Create(src, N);
- REPORTER_ASSERT(reporter, 1 == array->getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(*array, 1));
REPORTER_ASSERT(reporter, N == array->count());
REPORTER_ASSERT(reporter, 2*N == InstCounterClass::gInstCounter);
thing1.join();
thing2.join();
- REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
+ REPORTER_ASSERT(reporter, RefCntIs(*ref, 1));
ref->unref();
}
thing3.join();
thing4.join();
- REPORTER_ASSERT(reporter, ref->getRefCnt() == 1);
- REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1);
+ REPORTER_ASSERT(reporter, RefCntIs(*ref, 1));
+ REPORTER_ASSERT(reporter, WeakRefCntIs(*ref, 1));
ref->unref();
}
*/
#include "SkRefDict.h"
+#include "RefCntIs.h"
#include "Test.h"
class TestRC : public SkRefCnt {
dict.set("foo", &data0);
REPORTER_ASSERT(reporter, &data0 == dict.find("foo"));
- REPORTER_ASSERT(reporter, 2 == data0.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 2));
dict.set("foo", &data0);
REPORTER_ASSERT(reporter, &data0 == dict.find("foo"));
- REPORTER_ASSERT(reporter, 2 == data0.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 2));
dict.set("foo", &data1);
REPORTER_ASSERT(reporter, &data1 == dict.find("foo"));
- REPORTER_ASSERT(reporter, 1 == data0.getRefCnt());
- REPORTER_ASSERT(reporter, 2 == data1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(data1, 2));
dict.set("foo", NULL);
REPORTER_ASSERT(reporter, NULL == dict.find("foo"));
- REPORTER_ASSERT(reporter, 1 == data0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == data1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(data1, 1));
dict.set("foo", &data0);
dict.set("bar", &data1);
REPORTER_ASSERT(reporter, &data0 == dict.find("foo"));
REPORTER_ASSERT(reporter, &data1 == dict.find("bar"));
- REPORTER_ASSERT(reporter, 2 == data0.getRefCnt());
- REPORTER_ASSERT(reporter, 2 == data1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 2));
+ REPORTER_ASSERT(reporter, RefCntIs(data1, 2));
dict.set("foo", &data1);
REPORTER_ASSERT(reporter, &data1 == dict.find("foo"));
REPORTER_ASSERT(reporter, &data1 == dict.find("bar"));
- REPORTER_ASSERT(reporter, 1 == data0.getRefCnt());
- REPORTER_ASSERT(reporter, 3 == data1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(data1, 3));
dict.removeAll();
REPORTER_ASSERT(reporter, NULL == dict.find("foo"));
REPORTER_ASSERT(reporter, NULL == dict.find("bar"));
- REPORTER_ASSERT(reporter, 1 == data0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == data1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(data1, 1));
{
SkRefDict d;
REPORTER_ASSERT(reporter, NULL == d.find("foo"));
- REPORTER_ASSERT(reporter, 1 == data0.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 1));
d.set("foo", &data0);
REPORTER_ASSERT(reporter, &data0 == d.find("foo"));
- REPORTER_ASSERT(reporter, 2 == data0.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 2));
// let d go out of scope still with a ref on data0
}
// be sure d's destructor lowered data0's owner count back to 1
- REPORTER_ASSERT(reporter, 1 == data0.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(data0, 1));
}
#include "SkRRect.h"
#include "SkSurface.h"
#include "SkUtils.h"
+#include "RefCntIs.h"
#include "Test.h"
#if SK_SUPPORT_GPU
void* addr = sk_malloc_throw(size);
SkData* data = SkData::NewFromMalloc(addr, size);
- REPORTER_ASSERT(reporter, 1 == data->getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(*data, 1));
SkImage* image = SkImage::NewRasterData(info, data, rowBytes);
- REPORTER_ASSERT(reporter, 2 == data->getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(*data, 2));
image->unref();
- REPORTER_ASSERT(reporter, 1 == data->getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(*data, 1));
data->unref();
}
#include "SkTSearch.h"
#include "SkTSort.h"
#include "SkUtils.h"
+#include "RefCntIs.h"
#include "Test.h"
class RefClass : public SkRefCnt {
static void test_autounref(skiatest::Reporter* reporter) {
RefClass obj(0);
- REPORTER_ASSERT(reporter, 1 == obj.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj, 1));
SkAutoTUnref<RefClass> tmp(&obj);
REPORTER_ASSERT(reporter, &obj == tmp.get());
- REPORTER_ASSERT(reporter, 1 == obj.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj, 1));
REPORTER_ASSERT(reporter, &obj == tmp.detach());
- REPORTER_ASSERT(reporter, 1 == obj.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj, 1));
REPORTER_ASSERT(reporter, NULL == tmp.detach());
REPORTER_ASSERT(reporter, NULL == tmp.get());
obj.ref();
- REPORTER_ASSERT(reporter, 2 == obj.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj, 2));
{
SkAutoTUnref<RefClass> tmp2(&obj);
}
- REPORTER_ASSERT(reporter, 1 == obj.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj, 1));
}
static void test_autostarray(skiatest::Reporter* reporter) {
RefClass obj0(0);
RefClass obj1(1);
- REPORTER_ASSERT(reporter, 1 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 1));
{
SkAutoSTArray<2, SkRefPtr<RefClass> > tmp;
REPORTER_ASSERT(reporter, 4 == tmp.count());
tmp[0] = &obj0;
tmp[1] = &obj1;
- REPORTER_ASSERT(reporter, 2 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 2 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 2));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 2));
// test out reset with data in the array (and a new allocation)
tmp.reset(0);
REPORTER_ASSERT(reporter, 0 == tmp.count());
- REPORTER_ASSERT(reporter, 1 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 1));
tmp.reset(2); // this should use the preexisting allocation
REPORTER_ASSERT(reporter, 2 == tmp.count());
}
// test out destructor with data in the array (and using existing allocation)
- REPORTER_ASSERT(reporter, 1 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 1));
{
// test out allocating ctor (this should allocate new memory)
tmp[0] = &obj0;
tmp[1] = &obj1;
- REPORTER_ASSERT(reporter, 2 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 2 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 2));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 2));
// Test out resut with data in the array and malloced storage
tmp.reset(0);
- REPORTER_ASSERT(reporter, 1 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 1));
tmp.reset(2); // this should use the preexisting storage
tmp[0] = &obj0;
tmp[1] = &obj1;
- REPORTER_ASSERT(reporter, 2 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 2 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 2));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 2));
tmp.reset(4); // this should force a new malloc
- REPORTER_ASSERT(reporter, 1 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 1));
tmp[0] = &obj0;
tmp[1] = &obj1;
- REPORTER_ASSERT(reporter, 2 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 2 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 2));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 2));
}
- REPORTER_ASSERT(reporter, 1 == obj0.getRefCnt());
- REPORTER_ASSERT(reporter, 1 == obj1.getRefCnt());
+ REPORTER_ASSERT(reporter, RefCntIs(obj0, 1));
+ REPORTER_ASSERT(reporter, RefCntIs(obj1, 1));
}
/////////////////////////////////////////////////////////////////////////////
--- /dev/null
+#include "RefCntIs.h"
+
+bool RefCntIs(const SkRefCntBase& obj, int32_t n) {
+ return obj.fRefCnt == n;
+}
+
+bool WeakRefCntIs(const SkWeakRefCnt& obj, int32_t n) {
+ return obj.fWeakCnt == n;
+}
--- /dev/null
+#ifndef RefCntIs_DEFINED
+#define RefCntIs_DEFINED
+
+// Allows tests to assert a particular value for a ref count,
+// without letting Skia library code look at that value.
+
+#include "SkRefCnt.h"
+#include "SkWeakRefCnt.h"
+
+bool RefCntIs(const SkRefCntBase&, int32_t);
+bool WeakRefCntIs(const SkWeakRefCnt&, int32_t);
+
+#endif//RefCntIs_DEFINED
race:SkPixelRef::callGenIDChangeListeners
race:SkPixelRef::needsNewGenID
-# This calls SkRefCnt::getRefCnt(), which is not thread safe. skia:2726
-race:SkImageFilter::filterImage
-
# SkPathRef caches its bounding box the first time it's needed.
# This will be fixed naturally once we create (from a single thread) a
# bounding-box hierarchy for SkRecord-based SkPictures; all bounds will come pre-cached.