Rename GrThreadSafeUniquelyKeyedProxyViewCache
Once triangulated paths are added this will no longer just be storing proxy views.
Bug: 1108408
Change-Id: I82fa47b0b85f738d9a25330c29bc2892c9bfeda4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323999
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Adlai Holler <adlai@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrThreadSafeCache.cpp b/src/gpu/GrThreadSafeCache.cpp
new file mode 100644
index 0000000..0db8002
--- /dev/null
+++ b/src/gpu/GrThreadSafeCache.cpp
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/GrThreadSafeCache.h"
+
+#include "include/gpu/GrDirectContext.h"
+#include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrProxyProvider.h"
+#include "src/gpu/GrRenderTargetContext.h"
+#include "src/gpu/GrResourceCache.h"
+
+GrThreadSafeCache::GrThreadSafeCache()
+ : fFreeEntryList(nullptr) {
+}
+
+GrThreadSafeCache::~GrThreadSafeCache() {
+ this->dropAllRefs();
+}
+
+#if GR_TEST_UTILS
+int GrThreadSafeCache::numEntries() const {
+ SkAutoSpinlock lock{fSpinLock};
+
+ return fUniquelyKeyedProxyViewMap.count();
+}
+
+size_t GrThreadSafeCache::approxBytesUsedForHash() const {
+ SkAutoSpinlock lock{fSpinLock};
+
+ return fUniquelyKeyedProxyViewMap.approxBytesUsed();
+}
+#endif
+
+void GrThreadSafeCache::dropAllRefs() {
+ SkAutoSpinlock lock{fSpinLock};
+
+ fUniquelyKeyedProxyViewMap.reset();
+ while (auto tmp = fUniquelyKeyedProxyViewList.head()) {
+ fUniquelyKeyedProxyViewList.remove(tmp);
+ this->recycleEntry(tmp);
+ }
+ // TODO: should we empty out the fFreeEntryList and reset fEntryAllocator?
+}
+
+// TODO: If iterating becomes too expensive switch to using something like GrIORef for the
+// GrSurfaceProxy
+void GrThreadSafeCache::dropUniqueRefs(GrResourceCache* resourceCache) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ // Iterate from LRU to MRU
+ Entry* cur = fUniquelyKeyedProxyViewList.tail();
+ Entry* prev = cur ? cur->fPrev : nullptr;
+
+ while (cur) {
+ if (resourceCache && !resourceCache->overBudget()) {
+ return;
+ }
+
+ if (cur->fView.proxy()->unique()) {
+ fUniquelyKeyedProxyViewMap.remove(cur->fKey);
+ fUniquelyKeyedProxyViewList.remove(cur);
+ this->recycleEntry(cur);
+ }
+
+ cur = prev;
+ prev = cur ? cur->fPrev : nullptr;
+ }
+}
+
+void GrThreadSafeCache::dropUniqueRefsOlderThan(GrStdSteadyClock::time_point purgeTime) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ // Iterate from LRU to MRU
+ Entry* cur = fUniquelyKeyedProxyViewList.tail();
+ Entry* prev = cur ? cur->fPrev : nullptr;
+
+ while (cur) {
+ if (cur->fLastAccess >= purgeTime) {
+ // This entry and all the remaining ones in the list will be newer than 'purgeTime'
+ return;
+ }
+
+ if (cur->fView.proxy()->unique()) {
+ fUniquelyKeyedProxyViewMap.remove(cur->fKey);
+ fUniquelyKeyedProxyViewList.remove(cur);
+ this->recycleEntry(cur);
+ }
+
+ cur = prev;
+ prev = cur ? cur->fPrev : nullptr;
+ }
+}
+
+std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalFind(
+ const GrUniqueKey& key) {
+ Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
+ if (tmp) {
+ SkASSERT(fUniquelyKeyedProxyViewList.isInList(tmp));
+ // make the sought out entry the MRU
+ tmp->fLastAccess = GrStdSteadyClock::now();
+ fUniquelyKeyedProxyViewList.remove(tmp);
+ fUniquelyKeyedProxyViewList.addToHead(tmp);
+ return { tmp->fView, tmp->fKey.refCustomData() };
+ }
+
+ return {};
+}
+
+GrSurfaceProxyView GrThreadSafeCache::find(const GrUniqueKey& key) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ GrSurfaceProxyView view;
+ std::tie(view, std::ignore) = this->internalFind(key);
+ return view;
+}
+
+std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findWithData(
+ const GrUniqueKey& key) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ return this->internalFind(key);
+}
+
+GrThreadSafeCache::Entry* GrThreadSafeCache::getEntry(const GrUniqueKey& key,
+ const GrSurfaceProxyView& view) {
+ Entry* entry;
+
+ if (fFreeEntryList) {
+ entry = fFreeEntryList;
+ fFreeEntryList = entry->fNext;
+ entry->fNext = nullptr;
+
+ entry->fKey = key;
+ entry->fView = view;
+ } else {
+ entry = fEntryAllocator.make<Entry>(key, view);
+ }
+
+ // make 'entry' the MRU
+ entry->fLastAccess = GrStdSteadyClock::now();
+ fUniquelyKeyedProxyViewList.addToHead(entry);
+ fUniquelyKeyedProxyViewMap.add(entry);
+ return entry;
+}
+
+void GrThreadSafeCache::recycleEntry(Entry* dead) {
+ SkASSERT(!dead->fPrev && !dead->fNext && !dead->fList);
+
+ dead->fKey.reset();
+ dead->fView.reset();
+
+ dead->fNext = fFreeEntryList;
+ fFreeEntryList = dead;
+}
+
+std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::internalAdd(
+ const GrUniqueKey& key,
+ const GrSurfaceProxyView& view) {
+ Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
+ if (!tmp) {
+ tmp = this->getEntry(key, view);
+
+ SkASSERT(fUniquelyKeyedProxyViewMap.find(key));
+ }
+
+ return { tmp->fView, tmp->fKey.refCustomData() };
+}
+
+GrSurfaceProxyView GrThreadSafeCache::add(const GrUniqueKey& key, const GrSurfaceProxyView& view) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ GrSurfaceProxyView newView;
+ std::tie(newView, std::ignore) = this->internalAdd(key, view);
+ return newView;
+}
+
+std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::addWithData(
+ const GrUniqueKey& key,
+ const GrSurfaceProxyView& view) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ return this->internalAdd(key, view);
+}
+
+GrSurfaceProxyView GrThreadSafeCache::findOrAdd(const GrUniqueKey& key,
+ const GrSurfaceProxyView& v) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ GrSurfaceProxyView view;
+ std::tie(view, std::ignore) = this->internalFind(key);
+ if (view) {
+ return view;
+ }
+
+ std::tie(view, std::ignore) = this->internalAdd(key, v);
+ return view;
+}
+
+std::tuple<GrSurfaceProxyView, sk_sp<SkData>> GrThreadSafeCache::findOrAddWithData(
+ const GrUniqueKey& key,
+ const GrSurfaceProxyView& v) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ auto [view, data] = this->internalFind(key);
+ if (view) {
+ return { std::move(view), std::move(data) };
+ }
+
+ return this->internalAdd(key, v);
+}
+
+void GrThreadSafeCache::remove(const GrUniqueKey& key) {
+ SkAutoSpinlock lock{fSpinLock};
+
+ Entry* tmp = fUniquelyKeyedProxyViewMap.find(key);
+ if (tmp) {
+ fUniquelyKeyedProxyViewMap.remove(key);
+ fUniquelyKeyedProxyViewList.remove(tmp);
+ this->recycleEntry(tmp);
+ }
+}
+
+std::tuple<GrSurfaceProxyView, sk_sp<GrThreadSafeCache::Trampoline>>
+GrThreadSafeCache::CreateLazyView(GrDirectContext* dContext,
+ GrColorType origCT,
+ SkISize dimensions,
+ GrSurfaceOrigin origin,
+ SkBackingFit fit) {
+ GrProxyProvider* proxyProvider = dContext->priv().proxyProvider();
+
+ constexpr int kSampleCnt = 1;
+ auto [newCT, format] = GrRenderTargetContext::GetFallbackColorTypeAndFormat(
+ dContext, origCT, kSampleCnt);
+
+ if (newCT == GrColorType::kUnknown) {
+ return {GrSurfaceProxyView(nullptr), nullptr};
+ }
+
+ sk_sp<Trampoline> trampoline(new Trampoline);
+
+ GrProxyProvider::TextureInfo texInfo{ GrMipMapped::kNo, GrTextureType::k2D };
+
+ sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
+ [trampoline](
+ GrResourceProvider* resourceProvider,
+ const GrSurfaceProxy::LazySurfaceDesc&) -> GrSurfaceProxy::LazyCallbackResult {
+ if (!resourceProvider || !trampoline->fProxy ||
+ !trampoline->fProxy->isInstantiated()) {
+ return GrSurfaceProxy::LazyCallbackResult(nullptr, true);
+ }
+
+ SkASSERT(!trampoline->fProxy->peekTexture()->getUniqueKey().isValid());
+ return GrSurfaceProxy::LazyCallbackResult(
+ sk_ref_sp(trampoline->fProxy->peekTexture()));
+ },
+ format,
+ dimensions,
+ kSampleCnt,
+ GrInternalSurfaceFlags::kNone,
+ &texInfo,
+ GrMipmapStatus::kNotAllocated,
+ fit,
+ SkBudgeted::kYes,
+ GrProtected::kNo,
+ /* wrapsVkSecondaryCB */ false,
+ GrSurfaceProxy::UseAllocator::kYes);
+
+ // TODO: It seems like this 'newCT' usage should be 'origCT' but this is
+ // what GrRenderTargetContext::MakeWithFallback does
+ GrSwizzle swizzle = dContext->priv().caps()->getReadSwizzle(format, newCT);
+
+ return {{std::move(proxy), origin, swizzle}, std::move(trampoline)};
+}