aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/private/GrSurfaceProxy.h1
-rw-r--r--src/core/SkBlurImageFilter.cpp2
-rw-r--r--src/core/SkTMultiMap.h51
-rw-r--r--src/gpu/GrDrawingManager.cpp12
-rw-r--r--src/gpu/GrRenderTargetOpList.cpp20
-rw-r--r--src/gpu/GrResourceAllocator.cpp119
-rw-r--r--src/gpu/GrResourceAllocator.h17
-rw-r--r--src/gpu/GrResourceCache.h1
-rw-r--r--src/gpu/GrSurface.cpp17
-rw-r--r--src/gpu/GrSurfaceProxyPriv.h6
-rw-r--r--src/gpu/GrTextureOpList.cpp20
11 files changed, 167 insertions, 99 deletions
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 0eccdce32c..23f62195c2 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -130,6 +130,7 @@ protected:
void transferRefs() {
SkASSERT(fTarget);
+ SkASSERT(fTarget->fRefCnt > 0);
fTarget->fRefCnt += (fRefCnt-1); // don't xfer the proxy's creation ref
fTarget->fPendingReads += fPendingReads;
fTarget->fPendingWrites += fPendingWrites;
diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp
index bb2da09976..2f0759cfd5 100644
--- a/src/core/SkBlurImageFilter.cpp
+++ b/src/core/SkBlurImageFilter.cpp
@@ -578,7 +578,7 @@ sk_sp<SkSpecialImage> SkBlurImageFilterImpl::onFilterImage(SkSpecialImage* sourc
result = this->gpuFilter(source, sigma, input, inputBounds, dstBounds,
ctx.outputProperties());
} else
- #endif
+#endif
{
// If both sigmas will result in a zero width window, there is nothing to do.
if (sigma.x() < kZeroWindow && sigma.y() < kZeroWindow) {
diff --git a/src/core/SkTMultiMap.h b/src/core/SkTMultiMap.h
index 3d6e38e454..987a306661 100644
--- a/src/core/SkTMultiMap.h
+++ b/src/core/SkTMultiMap.h
@@ -34,6 +34,7 @@ public:
for ( ; !iter.done(); ++iter) {
ValueList* next;
for (ValueList* cur = &(*iter); cur; cur = next) {
+ HashTraits::OnFree(cur->fValue);
next = cur->fNext;
delete cur;
}
@@ -69,20 +70,7 @@ public:
list = list->fNext;
}
- if (list->fNext) {
- ValueList* next = list->fNext;
- list->fValue = next->fValue;
- list->fNext = next->fNext;
- delete next;
- } else if (prev) {
- prev->fNext = nullptr;
- delete list;
- } else {
- fHash.remove(key);
- delete list;
- }
-
- --fCount;
+ this->internalRemove(prev, list, key);
}
T* find(const Key& key) const {
@@ -105,6 +93,23 @@ public:
return nullptr;
}
+ template<class FindPredicate>
+ T* findAndRemove(const Key& key, const FindPredicate f) {
+ ValueList* list = fHash.find(key);
+
+ ValueList* prev = nullptr;
+ while (list) {
+ if (f(list->fValue)){
+ T* value = list->fValue;
+ this->internalRemove(prev, list, key);
+ return value;
+ }
+ prev = list;
+ list = list->fNext;
+ }
+ return nullptr;
+ }
+
int count() const { return fCount; }
#ifdef SK_DEBUG
@@ -168,6 +173,24 @@ public:
private:
SkTDynamicHash<ValueList, Key> fHash;
int fCount;
+
+ void internalRemove(ValueList* prev, ValueList* elem, const Key& key) {
+ if (elem->fNext) {
+ ValueList* next = elem->fNext;
+ elem->fValue = next->fValue;
+ elem->fNext = next->fNext;
+ delete next;
+ } else if (prev) {
+ prev->fNext = nullptr;
+ delete elem;
+ } else {
+ fHash.remove(key);
+ delete elem;
+ }
+
+ --fCount;
+ }
+
};
#endif
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index eaacac246e..1aaa6f7ad2 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -171,14 +171,16 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
}
#endif
- GrResourceAllocator alloc(fContext->resourceProvider());
- for (int i = 0; i < fOpLists.count(); ++i) {
- fOpLists[i]->gatherProxyIntervals(&alloc);
- }
+ {
+ GrResourceAllocator alloc(fContext->resourceProvider());
+ for (int i = 0; i < fOpLists.count(); ++i) {
+ fOpLists[i]->gatherProxyIntervals(&alloc);
+ }
#ifdef MDB_ALLOC_RESOURCES
- alloc.assign();
+ alloc.assign();
#endif
+ }
for (int i = 0; i < fOpLists.count(); ++i) {
if (!fOpLists[i]->instantiate(fContext->resourceProvider())) {
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 09486c7c99..e6b91ff9c6 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -257,14 +257,18 @@ bool GrRenderTargetOpList::copySurface(const GrCaps& caps,
}
void GrRenderTargetOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
- if (!fRecordedOps.count()) {
- return;
- }
-
unsigned int cur = alloc->numOps();
// Add the interval for all the writes to this opList's target
- alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1);
+ if (fRecordedOps.count()) {
+ alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1);
+ } else {
+ // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
+ // still need to add an interval for the destination so we create a fake op# for
+ // the missing clear op.
+ alloc->addInterval(fTarget.get());
+ alloc->incOps();
+ }
auto gather = [ alloc ] (GrSurfaceProxy* p) {
alloc->addInterval(p);
@@ -273,9 +277,11 @@ void GrRenderTargetOpList::gatherProxyIntervals(GrResourceAllocator* alloc) cons
const GrOp* op = fRecordedOps[i].fOp.get(); // only diff from the GrTextureOpList version
if (op) {
op->visitProxies(gather);
-
- alloc->incOps();
}
+
+ // Even though the op may have been moved we still need to increment the op count to
+ // keep all the math consistent.
+ alloc->incOps();
}
}
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 62f780b177..f263802448 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -7,8 +7,12 @@
#include "GrResourceAllocator.h"
+#include "GrGpuResourcePriv.h"
+#include "GrResourceProvider.h"
+#include "GrSurfacePriv.h"
#include "GrSurfaceProxy.h"
#include "GrSurfaceProxyPriv.h"
+#include "GrTextureProxy.h"
void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy,
unsigned int start, unsigned int end) {
@@ -17,15 +21,18 @@ void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy,
if (Interval* intvl = fIntvlHash.find(proxy->uniqueID().asUInt())) {
// Revise the interval for an existing use
- //SkASSERT(intvl->fEnd <= end);
- intvl->fEnd = end;
+ // TODO: this assert is failing on the copy_on_write_retain GM!
+ //SkASSERT(intvl->end() <= start);
+ if (intvl->end() < end) {
+ intvl->extendEnd(end);
+ }
return;
}
Interval* newIntvl;
if (fFreeIntervalList) {
newIntvl = fFreeIntervalList;
- fFreeIntervalList = newIntvl->fNext;
+ fFreeIntervalList = newIntvl->next();
newIntvl->resetTo(proxy, start, end);
} else {
newIntvl = fIntervalAllocator.make<Interval>(proxy, start, end);
@@ -38,7 +45,7 @@ void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy,
GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
Interval* temp = fHead;
if (temp) {
- fHead = temp->fNext;
+ fHead = temp->next();
}
return temp;
}
@@ -46,36 +53,36 @@ GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
// TODO: fuse this with insertByIncreasingEnd
void GrResourceAllocator::IntervalList::insertByIncreasingStart(Interval* intvl) {
if (!fHead) {
- intvl->fNext = nullptr;
+ intvl->setNext(nullptr);
fHead = intvl;
- } else if (intvl->fStart <= fHead->fStart) {
- intvl->fNext = fHead;
+ } else if (intvl->start() <= fHead->start()) {
+ intvl->setNext(fHead);
fHead = intvl;
} else {
Interval* prev = fHead;
- Interval* next = prev->fNext;
- for (; next && intvl->fStart > next->fStart; prev = next, next = next->fNext) {
+ Interval* next = prev->next();
+ for (; next && intvl->start() > next->start(); prev = next, next = next->next()) {
}
- intvl->fNext = next;
- prev->fNext = intvl;
+ intvl->setNext(next);
+ prev->setNext(intvl);
}
}
// TODO: fuse this with insertByIncreasingStart
void GrResourceAllocator::IntervalList::insertByIncreasingEnd(Interval* intvl) {
if (!fHead) {
- intvl->fNext = nullptr;
+ intvl->setNext(nullptr);
fHead = intvl;
- } else if (intvl->fEnd <= fHead->fEnd) {
- intvl->fNext = fHead;
+ } else if (intvl->end() <= fHead->end()) {
+ intvl->setNext(fHead);
fHead = intvl;
} else {
Interval* prev = fHead;
- Interval* next = prev->fNext;
- for (; next && intvl->fEnd > next->fEnd; prev = next, next = next->fNext) {
+ Interval* next = prev->next();
+ for (; next && intvl->end() > next->end(); prev = next, next = next->next()) {
}
- intvl->fNext = next;
- prev->fNext = intvl;
+ intvl->setNext(next);
+ prev->setNext(intvl);
}
}
@@ -87,8 +94,15 @@ void GrResourceAllocator::freeUpSurface(GrSurface* surface) {
return; // can't do it w/o a valid scratch key
}
+ if (surface->getUniqueKey().isValid()) {
+ // If the surface has a unique key we throw it back into the resource cache.
+ // If things get really tight 'findSurfaceFor' may pull it back out but there is
+ // no need to have it in tight rotation.
+ return;
+ }
+
// TODO: fix this insertion so we get a more LRU-ish behavior
- fFreePool.insert(key, surface);
+ fFreePool.insert(key, SkRef(surface));
}
// First try to reuse one of the recently allocated/used GrSurfaces in the free pool.
@@ -100,9 +114,19 @@ sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(const GrSurfaceProxy* proxy
proxy->priv().computeScratchKey(&key);
- GrSurface* surface = fFreePool.find(key);
+ auto filter = [&] (const GrSurface* s) {
+ return !proxy->priv().requiresNoPendingIO() || !s->surfacePriv().hasPendingIO();
+ };
+ sk_sp<GrSurface> surface(fFreePool.findAndRemove(key, filter));
if (surface) {
- return sk_ref_sp(surface);
+ if (SkBudgeted::kYes == proxy->isBudgeted() &&
+ SkBudgeted::kNo == surface->resourcePriv().isBudgeted()) {
+ // This gets the job done but isn't quite correct. It would be better to try to
+ // match budgeted proxies w/ budgeted surface and unbudgeted w/ unbudgeted.
+ surface->resourcePriv().makeBudgeted();
+ }
+
+ return surface;
}
// Failing that, try to grab a new one from the resource cache
@@ -112,12 +136,12 @@ sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(const GrSurfaceProxy* proxy
// Remove any intervals that end before the current index. Return their GrSurfaces
// to the free pool.
void GrResourceAllocator::expire(unsigned int curIndex) {
- while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->fEnd < curIndex) {
+ while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->end() < curIndex) {
Interval* temp = fActiveIntvls.popHead();
- this->freeUpSurface(temp->fProxy->priv().peekSurface());
+ this->freeUpSurface(temp->proxy()->priv().peekSurface());
// Add temp to the free interval list so it can be reused
- temp->fNext = fFreeIntervalList;
+ temp->setNext(fFreeIntervalList);
fFreeIntervalList = temp;
}
}
@@ -127,51 +151,26 @@ void GrResourceAllocator::assign() {
SkDEBUGCODE(fAssigned = true;)
while (Interval* cur = fIntvlList.popHead()) {
- this->expire(cur->fStart);
+ this->expire(cur->start());
- if (cur->fProxy->priv().isInstantiated()) {
+ if (cur->proxy()->priv().isInstantiated()) {
fActiveIntvls.insertByIncreasingEnd(cur);
continue;
}
// TODO: add over budget handling here?
- sk_sp<GrSurface> surface = this->findSurfaceFor(cur->fProxy);
+ sk_sp<GrSurface> surface = this->findSurfaceFor(cur->proxy());
if (surface) {
- cur->fProxy->priv().assign(std::move(surface));
+ // TODO: make getUniqueKey virtual on GrSurfaceProxy
+ GrTextureProxy* tex = cur->proxy()->asTextureProxy();
+ if (tex && tex->getUniqueKey().isValid()) {
+ fResourceProvider->assignUniqueKeyToResource(tex->getUniqueKey(), surface.get());
+ SkASSERT(surface->getUniqueKey() == tex->getUniqueKey());
+ }
+
+ cur->proxy()->priv().assign(std::move(surface));
}
// TODO: handle resouce allocation failure upstack
fActiveIntvls.insertByIncreasingEnd(cur);
}
}
-
-#ifdef SK_DEBUG
-void GrResourceAllocator::dump() {
- unsigned int min = fNumOps+1;
- unsigned int max = 0;
- for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->fNext) {
- SkDebugf("{ %d,%d }: [%d, %d]\n",
- cur->fProxy->uniqueID().asUInt(), cur->fProxy->underlyingUniqueID().asUInt(),
- cur->fStart, cur->fEnd);
- if (min > cur->fStart) {
- min = cur->fStart;
- }
- if (max < cur->fEnd) {
- max = cur->fEnd;
- }
- }
-
- for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->fNext) {
- SkDebugf("{ %3d,%3d }: ",
- cur->fProxy->uniqueID().asUInt(), cur->fProxy->underlyingUniqueID().asUInt());
- for (unsigned int i = min; i <= max; ++i) {
- if (i >= cur->fStart && i <= cur->fEnd) {
- SkDebugf("x");
- } else {
- SkDebugf(" ");
- }
- }
- SkDebugf("\n");
- }
-}
-#endif
-
diff --git a/src/gpu/GrResourceAllocator.h b/src/gpu/GrResourceAllocator.h
index 3be4836ca9..d7aed0591e 100644
--- a/src/gpu/GrResourceAllocator.h
+++ b/src/gpu/GrResourceAllocator.h
@@ -54,7 +54,6 @@ public:
}
void assign();
- SkDEBUGCODE(void dump();)
private:
class Interval;
@@ -72,6 +71,7 @@ private:
}
static uint32_t Hash(const GrScratchKey& key) { return key.hash(); }
+ static void OnFree(GrSurface* s) { s->unref(); }
};
typedef SkTMultiMap<GrSurface, GrScratchKey, FreePoolTraits> FreePoolMultiMap;
@@ -98,12 +98,27 @@ private:
fNext = nullptr;
}
+ const GrSurfaceProxy* proxy() const { return fProxy; }
+ GrSurfaceProxy* proxy() { return fProxy; }
+ unsigned int start() const { return fStart; }
+ unsigned int end() const { return fEnd; }
+ const Interval* next() const { return fNext; }
+ Interval* next() { return fNext; }
+
+ void setNext(Interval* next) { fNext = next; }
+
+ void extendEnd(unsigned int newEnd) {
+ SkASSERT(newEnd >= fEnd);
+ fEnd = newEnd;
+ }
+
// for SkTDynamicHash
static const uint32_t& GetKey(const Interval& intvl) {
return intvl.fProxyID;
}
static uint32_t Hash(const uint32_t& key) { return key; }
+ private:
GrSurfaceProxy* fProxy;
uint32_t fProxyID; // This is here b.c. DynamicHash requires a ref to the key
unsigned int fStart;
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 771196c81c..94245328f1 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -368,6 +368,7 @@ private:
}
static uint32_t Hash(const GrScratchKey& key) { return key.hash(); }
+ static void OnFree(GrGpuResource*) { }
};
typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap;
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index 24b42f3507..ec503d7066 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -9,6 +9,7 @@
#include "GrContext.h"
#include "GrOpList.h"
#include "GrRenderTarget.h"
+#include "GrResourceProvider.h"
#include "GrSurfacePriv.h"
#include "GrTexture.h"
@@ -18,8 +19,12 @@
size_t GrSurface::WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2) {
size_t size;
- int width = useNextPow2 ? GrNextPow2(desc.fWidth) : desc.fWidth;
- int height = useNextPow2 ? GrNextPow2(desc.fHeight) : desc.fHeight;
+ int width = useNextPow2
+ ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(desc.fWidth))
+ : desc.fWidth;
+ int height = useNextPow2
+ ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(desc.fHeight))
+ : desc.fHeight;
bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
if (isRenderTarget) {
@@ -53,8 +58,12 @@ size_t GrSurface::ComputeSize(GrPixelConfig config,
int colorSamplesPerPixel,
GrMipMapped mipMapped,
bool useNextPow2) {
- width = useNextPow2 ? GrNextPow2(width) : width;
- height = useNextPow2 ? GrNextPow2(height) : height;
+ width = useNextPow2
+ ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(width))
+ : width;
+ height = useNextPow2
+ ? SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(height))
+ : height;
SkASSERT(kUnknown_GrPixelConfig != config);
size_t colorSize = (size_t)width * height * GrBytesPerPixel(config);
diff --git a/src/gpu/GrSurfaceProxyPriv.h b/src/gpu/GrSurfaceProxyPriv.h
index f88c5cdfd9..1f953f401d 100644
--- a/src/gpu/GrSurfaceProxyPriv.h
+++ b/src/gpu/GrSurfaceProxyPriv.h
@@ -10,6 +10,8 @@
#include "GrSurfaceProxy.h"
+#include "GrResourceProvider.h"
+
/** Class that adds methods to GrSurfaceProxy that are only intended for use internal to Skia.
This class is purely a privileged window into GrSurfaceProxy. It should never have additional
data members or virtual methods. */
@@ -56,6 +58,10 @@ public:
// Assign this proxy the provided GrSurface as its backing surface
void assign(sk_sp<GrSurface> surface) { fProxy->assign(std::move(surface)); }
+ bool requiresNoPendingIO() const {
+ return fProxy->fFlags & GrResourceProvider::kNoPendingIO_Flag;
+ }
+
// Don't abuse this call!!!!!!!
bool isExact() const { return SkBackingFit::kExact == fProxy->fFit; }
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index 9a3d15be97..5c4fe3cc06 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -124,14 +124,18 @@ bool GrTextureOpList::copySurface(const GrCaps& caps,
}
void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
- if (!fRecordedOps.count()) {
- return;
- }
-
unsigned int cur = alloc->numOps();
// Add the interval for all the writes to this opList's target
- alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1);
+ if (fRecordedOps.count()) {
+ alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1);
+ } else {
+ // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
+ // still need to add an interval for the destination so we create a fake op# for
+ // the missing clear op.
+ alloc->addInterval(fTarget.get());
+ alloc->incOps();
+ }
auto gather = [ alloc ] (GrSurfaceProxy* p) {
alloc->addInterval(p);
@@ -140,9 +144,11 @@ void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
if (op) {
op->visitProxies(gather);
-
- alloc->incOps();
}
+
+ // Even though the op may have been moved we still need to increment the op count to
+ // keep all the math consistent.
+ alloc->incOps();
}
}