aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2016-09-06 12:38:00 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-06 12:38:00 -0700
commit1dbb207babecdae8f1f74ed9d9900c73064df744 (patch)
tree179554685d20ab291fe8ecfb89b4e2b8f98c44c7
parent0a441077dccd8b33ed1af3193b9d5df5143d4861 (diff)
Restructure flushing relationship between GrContext, GrDrawingManager, and GrResourceCache.
Consolidates all flush actions into GrDrawingManager and makes GrContext::flush a passthrough. Removes the unused and untested discard flush variation. Replaces the indirect overbudget callback mechanism of GrResourceCache with a flag set by resource cache when it wants to flush that is checked after each draw by GrDrawContext. Modifies GrResourceCache::notifyFlushOccurred() to take a param indicating whether it triggered the flush that just occurred. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2307053002 Review-Url: https://codereview.chromium.org/2307053002
-rw-r--r--include/gpu/GrContext.h31
-rw-r--r--src/gpu/GrContext.cpp35
-rw-r--r--src/gpu/GrDrawContext.cpp2
-rw-r--r--src/gpu/GrDrawingManager.cpp13
-rw-r--r--src/gpu/GrDrawingManager.h17
-rw-r--r--src/gpu/GrResourceCache.cpp37
-rw-r--r--src/gpu/GrResourceCache.h29
-rw-r--r--src/gpu/SkGpuDevice.cpp1
-rw-r--r--tests/ResourceCacheTest.cpp10
9 files changed, 70 insertions, 105 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index f14c36e35c..996b77f2db 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -214,31 +214,10 @@ public:
// Misc.
/**
- * Flags that affect flush() behavior.
- */
- enum FlushBits {
- /**
- * A client may reach a point where it has partially rendered a frame
- * through a GrContext that it knows the user will never see. This flag
- * causes the flush to skip submission of deferred content to the 3D API
- * during the flush.
- */
- kDiscard_FlushBit = 0x2,
- };
-
- /**
* Call to ensure all drawing to the context has been issued to the
* underlying 3D API.
- * @param flagsBitfield flags that control the flushing behavior. See
- * FlushBits.
*/
- void flush(int flagsBitfield = 0);
-
- void flushIfNecessary() {
- if (fFlushToReduceCacheSize || this->caps()->immediateFlush()) {
- this->flush();
- }
- }
+ void flush();
/**
* These flags can be used with the read/write pixels functions below.
@@ -409,8 +388,6 @@ private:
GrBatchFontCache* fBatchFontCache;
SkAutoTDelete<GrTextBlobCache> fTextBlobCache;
- // Set by OverbudgetCB() to request that GrContext flush before exiting a draw.
- bool fFlushToReduceCacheSize;
bool fDidTestPMConversions;
int fPMToUPMConversion;
int fUPMToPMConversion;
@@ -472,12 +449,6 @@ private:
bool didFailPMUPMConversionTest() const;
/**
- * This callback allows the resource cache to callback into the GrContext
- * when the cache is still over budget after a purge.
- */
- static void OverBudgetCB(void* data);
-
- /**
* A callback similar to the above for use by the TextBlobCache
* TODO move textblob draw calls below context so we can use the call above.
*/
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 3f4d2fa959..357f58e6e3 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -66,7 +66,6 @@ GrContext::GrContext() : fUniqueID(next_id()) {
fResourceCache = nullptr;
fResourceProvider = nullptr;
fBatchFontCache = nullptr;
- fFlushToReduceCacheSize = false;
}
bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
@@ -87,7 +86,6 @@ void GrContext::initCommon(const GrContextOptions& options) {
fCaps = SkRef(fGpu->caps());
fResourceCache = new GrResourceCache(fCaps);
- fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
fDidTestPMConversions = false;
@@ -97,7 +95,8 @@ void GrContext::initCommon(const GrContextOptions& options) {
dtOptions.fDrawBatchBounds = options.fDrawBatchBounds;
dtOptions.fMaxBatchLookback = options.fMaxBatchLookback;
dtOptions.fMaxBatchLookahead = options.fMaxBatchLookahead;
- fDrawingManager.reset(new GrDrawingManager(this, dtOptions, &fSingleOwner));
+ fDrawingManager.reset(new GrDrawingManager(this, dtOptions, options.fImmediateMode,
+ &fSingleOwner));
// GrBatchFontCache will eventually replace GrFontCache
fBatchFontCache = new GrBatchFontCache(this);
@@ -203,41 +202,21 @@ void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes)
////////////////////////////////////////////////////////////////////////////////
-void GrContext::OverBudgetCB(void* data) {
- SkASSERT(data);
-
- GrContext* context = reinterpret_cast<GrContext*>(data);
-
- // Flush the GrBufferedDrawTarget to possibly free up some textures
- context->fFlushToReduceCacheSize = true;
-}
-
void GrContext::TextBlobCacheOverBudgetCB(void* data) {
SkASSERT(data);
-
- // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
- // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
- // drawText calls to below the GrContext level, but this is not trivial because they call
- // drawPath on SkGpuDevice
+ // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on GrDrawContext
+ // to perform a necessary flush. The solution is to move drawText calls to below the GrContext
+ // level, but this is not trivial because they call drawPath on SkGpuDevice.
GrContext* context = reinterpret_cast<GrContext*>(data);
context->flush();
}
////////////////////////////////////////////////////////////////////////////////
-void GrContext::flush(int flagsBitfield) {
+void GrContext::flush() {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
- bool flushed = false;
- if (kDiscard_FlushBit & flagsBitfield) {
- fDrawingManager->reset();
- } else {
- flushed = fDrawingManager->flush();
- }
- if (flushed) {
- fResourceCache->notifyFlushOccurred();
- }
- fFlushToReduceCacheSize = false;
+ fDrawingManager->flush();
}
bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 87252f3979..ed02602499 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -59,7 +59,7 @@ public:
AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
SkASSERT(fDrawingManager);
}
- ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
+ ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
private:
GrDrawingManager* fDrawingManager;
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 6c75c0d147..4642e1a3fe 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -5,8 +5,10 @@
* found in the LICENSE file.
*/
-#include "GrDrawContext.h"
#include "GrDrawingManager.h"
+
+#include "GrContext.h"
+#include "GrDrawContext.h"
#include "GrDrawTarget.h"
#include "GrPathRenderingDrawContext.h"
#include "GrResourceProvider.h"
@@ -74,9 +76,9 @@ void GrDrawingManager::reset() {
fFlushState.reset();
}
-bool GrDrawingManager::flush() {
+void GrDrawingManager::internalFlush(GrResourceCache::FlushType type) {
if (fFlushing || this->wasAbandoned()) {
- return false;
+ return;
}
fFlushing = true;
bool flushed = false;
@@ -126,8 +128,11 @@ bool GrDrawingManager::flush() {
#endif
fFlushState.reset();
+ // We always have to notify the cache when it requested a flush so it can reset its state.
+ if (flushed || type == GrResourceCache::FlushType::kCacheRequested) {
+ fContext->getResourceCache()->notifyFlushOccurred(type);
+ }
fFlushing = false;
- return flushed;
}
GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 745820f439..bc6f7a361a 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -13,6 +13,7 @@
#include "GrBatchFlushState.h"
#include "GrPathRendererChain.h"
#include "GrPathRenderer.h"
+#include "GrResourceCache.h"
#include "SkTDArray.h"
class GrContext;
@@ -49,11 +50,19 @@ public:
GrPathRendererChain::DrawType drawType,
GrPathRenderer::StencilSupport* stencilSupport = NULL);
+ void flushIfNecessary() {
+ if (fContext->getResourceCache()->requestsFlush()) {
+ this->internalFlush(GrResourceCache::kCacheRequested);
+ } else if (fIsImmediateMode) {
+ this->internalFlush(GrResourceCache::kImmediateMode);
+ }
+ }
+
static bool ProgramUnitTest(GrContext* context, int maxStages);
private:
GrDrawingManager(GrContext* context, const GrDrawTarget::Options& optionsForDrawTargets,
- GrSingleOwner* singleOwner)
+ bool isImmediateMode, GrSingleOwner* singleOwner)
: fContext(context)
, fOptionsForDrawTargets(optionsForDrawTargets)
, fSingleOwner(singleOwner)
@@ -68,8 +77,8 @@ private:
void abandon();
void cleanup();
void reset();
- /** Returns true if there was anything to flush and false otherwise */
- bool flush();
+ void flush() { this->internalFlush(GrResourceCache::FlushType::kExternal); }
+ void internalFlush(GrResourceCache::FlushType);
friend class GrContext; // for access to: ctor, abandon, reset & flush
@@ -92,6 +101,8 @@ private:
GrBatchFlushState fFlushState;
bool fFlushing;
+
+ bool fIsImmediateMode;
};
#endif
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 62360ed535..e3f4f9ff50 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -73,8 +73,6 @@ GrResourceCache::GrResourceCache(const GrCaps* caps)
, fBytes(0)
, fBudgetedCount(0)
, fBudgetedBytes(0)
- , fOverBudgetCB(nullptr)
- , fOverBudgetData(nullptr)
, fFlushTimestamps(nullptr)
, fLastFlushTimestampIndex(0)
, fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) {
@@ -503,10 +501,9 @@ void GrResourceCache::purgeAsNeeded() {
this->validate();
if (stillOverbudget) {
- // Despite the purge we're still over budget. Call our over budget callback. If this frees
- // any resources then we'll get notified and take appropriate action.
- (*fOverBudgetCB)(fOverBudgetData);
- this->validate();
+ // Set this so that GrDrawingManager will issue a flush to free up resources with pending
+ // IO that we were unable to purge in this pass.
+ fRequestFlush = true;
}
}
@@ -621,16 +618,26 @@ uint32_t GrResourceCache::getNextTimestamp() {
return fTimestamp++;
}
-void GrResourceCache::notifyFlushOccurred() {
- if (fFlushTimestamps) {
- SkASSERT(SkIsPow2(fMaxUnusedFlushes));
- fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlushes - 1);
- // get the timestamp before accessing fFlushTimestamps because getNextTimestamp will
- // reallocate fFlushTimestamps on timestamp overflow.
- uint32_t timestamp = this->getNextTimestamp();
- fFlushTimestamps[fLastFlushTimestampIndex] = timestamp;
- this->purgeAsNeeded();
+void GrResourceCache::notifyFlushOccurred(FlushType type) {
+ switch (type) {
+ case FlushType::kImmediateMode:
+ break;
+ case FlushType::kCacheRequested:
+ SkASSERT(fRequestFlush);
+ fRequestFlush = false;
+ break;
+ case FlushType::kExternal:
+ if (fFlushTimestamps) {
+ SkASSERT(SkIsPow2(fMaxUnusedFlushes));
+ fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlushes - 1);
+ // get the timestamp before accessing fFlushTimestamps because getNextTimestamp will
+ // reallocate fFlushTimestamps on timestamp overflow.
+ uint32_t timestamp = this->getNextTimestamp();
+ fFlushTimestamps[fLastFlushTimestampIndex] = timestamp;
+ }
+ break;
}
+ this->purgeAsNeeded();
}
void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index 6c64ddc933..bf7b237006 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -11,6 +11,7 @@
#include "GrGpuResource.h"
#include "GrGpuResourceCacheAccess.h"
#include "GrGpuResourcePriv.h"
+#include "GrResourceCache.h"
#include "GrResourceKey.h"
#include "SkMessageBus.h"
#include "SkRefCnt.h"
@@ -163,23 +164,16 @@ public:
/** Purges all resources that don't have external owners. */
void purgeAllUnlocked();
- /**
- * The callback function used by the cache when it is still over budget after a purge. The
- * passed in 'data' is the same 'data' handed to setOverbudgetCallback.
- */
- typedef void (*PFOverBudgetCB)(void* data);
+ /** Returns true if the cache would like a flush to occur in order to make more resources
+ purgeable. */
+ bool requestsFlush() const { return fRequestFlush; }
- /**
- * Set the callback the cache should use when it is still over budget after a purge. The 'data'
- * provided here will be passed back to the callback. Note that the cache will attempt to purge
- * any resources newly freed by the callback.
- */
- void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) {
- fOverBudgetCB = overBudgetCB;
- fOverBudgetData = data;
- }
-
- void notifyFlushOccurred();
+ enum FlushType {
+ kExternal,
+ kImmediateMode,
+ kCacheRequested,
+ };
+ void notifyFlushOccurred(FlushType);
#if GR_CACHE_STATS
struct Stats {
@@ -326,8 +320,7 @@ private:
int fBudgetedCount;
size_t fBudgetedBytes;
- PFOverBudgetCB fOverBudgetCB;
- void* fOverBudgetData;
+ bool fRequestFlush;
// We keep track of the "timestamps" of the last n flushes. If a resource hasn't been used in
// that time then we well preemptively purge it to reduce memory usage.
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 64df998e2f..790a19a506 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1008,7 +1008,6 @@ void SkGpuDevice::drawBitmapTile(const SkBitmap& bitmap,
if (nullptr == texture) {
return;
}
-
sk_sp<GrColorSpaceXform> colorSpaceXform =
GrColorSpaceXform::Make(bitmap.colorSpace(), fDrawContext->getColorSpace());
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 2cbf81c231..b568485e4b 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -1133,7 +1133,7 @@ static void test_flush(skiatest::Reporter* reporter) {
make_unique_key<1>(&k, i);
r->resourcePriv().setUniqueKey(k);
r->unref();
- cache->notifyFlushOccurred();
+ cache->notifyFlushOccurred(GrResourceCache::kExternal);
}
// Send flush notifications to the cache. Each flush should purge the oldest resource.
@@ -1147,7 +1147,7 @@ static void test_flush(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, !SkToBool(r));
SkSafeUnref(r);
}
- cache->notifyFlushOccurred();
+ cache->notifyFlushOccurred(GrResourceCache::kExternal);
}
REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());
@@ -1169,13 +1169,13 @@ static void test_flush(skiatest::Reporter* reporter) {
} else {
r->unref();
}
- cache->notifyFlushOccurred();
+ cache->notifyFlushOccurred(GrResourceCache::kExternal);
}
for (int i = 0; i < kFlushCount; ++i) {
// Should get a resource purged every other flush.
REPORTER_ASSERT(reporter, kFlushCount - i/2 - 1 == cache->getResourceCount());
- cache->notifyFlushOccurred();
+ cache->notifyFlushOccurred(GrResourceCache::kExternal);
}
// Unref all the resources that we kept refs on in the first loop.
@@ -1187,7 +1187,7 @@ static void test_flush(skiatest::Reporter* reporter) {
// get kFlushCount additional flushes. Then everything should be purged.
for (int i = 0; i < kFlushCount; ++i) {
REPORTER_ASSERT(reporter, kFlushCount >> 1 == cache->getResourceCount());
- cache->notifyFlushOccurred();
+ cache->notifyFlushOccurred(GrResourceCache::kExternal);
}
REPORTER_ASSERT(reporter, 0 == cache->getResourceCount());