Implement caching of filled paths in the tessellated path renderer.
Paths are cached as tessellated triangle meshes in vertex buffers on the GPU. Stroked paths are not (yet) cached.
Paths containing no curved segments (linear paths) are reused at all scales. Paths containing curved segments are reused within a scale tolerance threshold.
In order to invalidate the cache when an SkPath is changed or deleted,
this required implementing genID change notification in SkPath. This is
modelled almost exactly on SkPixelRef::GenIDChangeListener.
However, It does not currently implement the check for unique genIDs,
so notifiers will fire when the first instance of an SkPathRef
using a given genID is destroyed.
Another caveat is that you cannot successfully add a change notifier
to an empty path, since it uses the "canonical" empty path which is
never modified or destroyed. For this reason, we prevent adding
listeners to it.
BUG=skia:4121,skia:4122, 497403
DOCS_PREVIEW= https://skia.org/?cl=1114353004
Review URL: https://codereview.chromium.org/1114353004
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index b795b01..65b7b7c 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -845,6 +845,20 @@
REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes());
REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive());
+
+ {
+ GrUniqueKey key2;
+ make_unique_key<0>(&key2, 0);
+ SkAutoTUnref<TestResource> d(SkNEW_ARGS(TestResource, (context->getGpu())));
+ int foo = 4132;
+ key2.setCustomData(SkData::NewWithCopy(&foo, sizeof(foo)));
+ d->resourcePriv().setUniqueKey(key2);
+ }
+
+ GrUniqueKey key3;
+ make_unique_key<0>(&key3, 0);
+ SkAutoTUnref<GrGpuResource> d2(cache->findAndRefUniqueResource(key3));
+ REPORTER_ASSERT(reporter, *(int*) d2->getUniqueKey().getCustomData()->data() == 4132);
}
static void test_purge_invalidated(skiatest::Reporter* reporter) {
@@ -1223,6 +1237,18 @@
}
}
+static void test_custom_data(skiatest::Reporter* reporter) {
+ GrUniqueKey key1, key2;
+ int foo = 4132;
+ key1.setCustomData(SkData::NewWithCopy(&foo, sizeof(foo)));
+ REPORTER_ASSERT(reporter, *(int*) key1.getCustomData()->data() == 4132);
+ REPORTER_ASSERT(reporter, key2.getCustomData() == nullptr);
+
+ // Test that copying a key also takes a ref on its custom data.
+ GrUniqueKey key3 = key1;
+ REPORTER_ASSERT(reporter, *(int*) key3.getCustomData()->data() == 4132);
+}
+
////////////////////////////////////////////////////////////////////////////////
DEF_GPUTEST(ResourceCache, reporter, factory) {
for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
@@ -1262,6 +1288,7 @@
test_timestamp_wrap(reporter);
test_flush(reporter);
test_large_resource_count(reporter);
+ test_custom_data(reporter);
}
#endif