Adding API to SkGPipe and SkDeferredCanvas for controlling memory usage externally
BUG=http://code.google.com/p/chromium/issues/detail?id=136828
Review URL: https://codereview.appspot.com/6454102
git-svn-id: http://skia.googlecode.com/svn/trunk@4971 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 2bcecf9..acac47c 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -164,6 +164,18 @@
this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
}
+size_t SkDeferredCanvas::storageAllocatedForRecording() const {
+ return this->getDeferredDevice()->storageAllocatedForRecording();
+}
+
+size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
+#if SK_DEFERRED_CANVAS_USES_GPIPE
+ return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
+#else
+ return 0;
+#endif
+}
+
void SkDeferredCanvas::validate() const {
SkASSERT(getDevice());
}
@@ -690,12 +702,34 @@
fImmediateCanvas->flush();
}
+#if SK_DEFERRED_CANVAS_USES_GPIPE
+size_t SkDeferredCanvas::DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
+ return fPipeWriter.freeMemoryIfPossible(bytesToFree);
+}
+#endif
+
+size_t SkDeferredCanvas::DeferredDevice::storageAllocatedForRecording() const {
+#if SK_DEFERRED_CANVAS_USES_GPIPE
+ return (fPipeController.storageAllocatedForRecording()
+ + fPipeWriter.storageAllocatedForRecording());
+#else
+ return 0;
+#endif
+}
+
SkCanvas* SkDeferredCanvas::DeferredDevice::recordingCanvas() {
#if SK_DEFERRED_CANVAS_USES_GPIPE
- if (fPipeController.storageAllocatedForRecording()
- + fPipeWriter.storageAllocatedForRecording()
- > fMaxRecordingStorageBytes) {
- this->flushPending();
+ size_t storageAllocated = this->storageAllocatedForRecording();
+ if (storageAllocated > fMaxRecordingStorageBytes) {
+ // First, attempt to reduce cache without flushing
+ size_t tryFree = storageAllocated - fMaxRecordingStorageBytes;
+ if (this->freeMemoryIfPossible(tryFree) < tryFree) {
+ // Flush is necessary to free more space.
+ this->flushPending();
+ // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes
+ // which could cause a high flushing frequency.
+ this->freeMemoryIfPossible(~0);
+ }
}
#endif
return fRecordingCanvas;