aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils
diff options
context:
space:
mode:
authorGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-23 13:35:14 +0000
committerGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-23 13:35:14 +0000
commitbfeddae9da240693441556b2f278827e213f75e8 (patch)
treeda8eae02490967677ab398adef409ea0bfdcf6ca /src/utils
parent47580694fbe974a065caf7c39c3d2075708c2018 (diff)
Fix unbound memory consumption problem with run away deferred canvases.
With this CL, deferred canvases will trigger a flush when then the memory allocated for recording commands (including flattened objects) exceeds 64MB. TEST=DeferredCanvas skia unit test, test step TestDeferredCanvasMemoryLimit BUG=http://code.google.com/p/chromium/issues/detail?id=137884 Review URL: https://codereview.appspot.com/6425053 git-svn-id: http://skia.googlecode.com/svn/trunk@4714 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/SkDeferredCanvas.cpp38
1 files changed, 31 insertions, 7 deletions
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 568f9a79a4..728e3d39d3 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -15,6 +15,11 @@
SK_DEFINE_INST_COUNT(SkDeferredCanvas::DeviceContext)
+enum {
+ // Deferred canvas will auto-flush when recording reaches this limit
+ kDefaultMaxRecordingStorageBytes = 64*1024*1024,
+};
+
namespace {
bool isPaintOpaque(const SkPaint* paint,
@@ -100,6 +105,11 @@ void SkDeferredCanvas::init() {
fDeferredDrawing = true; // On by default
}
+void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
+ validate();
+ this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
+}
+
void SkDeferredCanvas::validate() const {
SkASSERT(getDevice());
}
@@ -482,7 +492,7 @@ void SkDeferredCanvas::DeferredPipeController::playback() {
fBlockList.reset();
if (fBlock) {
- fReader.playback(fBlock,fBytesWritten);
+ fReader.playback(fBlock, fBytesWritten);
fBlock = NULL;
}
@@ -507,6 +517,7 @@ SkDeferredCanvas::DeferredDevice::DeferredDevice(
immediateDevice->height(), immediateDevice->isOpaque())
, fFreshFrame(true) {
+ fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
fDeviceContext = deviceContext;
SkSafeRef(fDeviceContext);
fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas
@@ -522,6 +533,10 @@ SkDeferredCanvas::DeferredDevice::~DeferredDevice() {
SkSafeUnref(fDeviceContext);
}
+void SkDeferredCanvas::DeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
+ fMaxRecordingStorageBytes = maxStorage;
+ recordingCanvas(); // Accessing the recording canvas applies the new limit.
+}
void SkDeferredCanvas::DeferredDevice::endRecording() {
#if SK_DEFERRED_CANVAS_USES_GPIPE
@@ -613,10 +628,19 @@ void SkDeferredCanvas::DeferredDevice::flushPending() {
}
void SkDeferredCanvas::DeferredDevice::flush() {
- flushPending();
+ this->flushPending();
fImmediateCanvas->flush();
}
+SkCanvas* SkDeferredCanvas::DeferredDevice::recordingCanvas() {
+#if SK_DEFERRED_CANVAS_USES_GPIPE
+ if (fPipeController.storageAllocatedForRecording() > fMaxRecordingStorageBytes) {
+ this->flushPending();
+ }
+#endif
+ return fRecordingCanvas;
+}
+
void SkDeferredCanvas::DeferredDevice::flushIfNeeded(const SkBitmap& bitmap) {
#if SK_DEFERRED_CANVAS_USES_GPIPE
if (bitmap.isImmutable()) {
@@ -632,7 +656,7 @@ void SkDeferredCanvas::DeferredDevice::flushIfNeeded(const SkBitmap& bitmap) {
// For now, drawing a writable bitmap triggers a flush
// TODO: implement read-only semantics and auto buffer duplication on write
// in SkBitmap/SkPixelRef, which will make deferral possible in this case.
- flushPending();
+ this->flushPending();
}
uint32_t SkDeferredCanvas::DeferredDevice::getDeviceCapabilities() {
@@ -648,7 +672,7 @@ int SkDeferredCanvas::DeferredDevice::height() const {
}
SkGpuRenderTarget* SkDeferredCanvas::DeferredDevice::accessRenderTarget() {
- flushPending();
+ this->flushPending();
return fImmediateDevice->accessRenderTarget();
}
@@ -664,7 +688,7 @@ void SkDeferredCanvas::DeferredDevice::writePixels(const SkBitmap& bitmap,
SkCanvas::kNative_Premul_Config8888 != config8888 &&
kPMColorAlias != config8888) {
//Special case config: no deferral
- flushPending();
+ this->flushPending();
fImmediateDevice->writePixels(bitmap, x, y, config8888);
}
@@ -675,7 +699,7 @@ void SkDeferredCanvas::DeferredDevice::writePixels(const SkBitmap& bitmap,
}
const SkBitmap& SkDeferredCanvas::DeferredDevice::onAccessBitmap(SkBitmap*) {
- flushPending();
+ this->flushPending();
return fImmediateDevice->accessBitmap(false);
}
@@ -694,7 +718,7 @@ SkDevice* SkDeferredCanvas::DeferredDevice::onCreateCompatibleDevice(
bool SkDeferredCanvas::DeferredDevice::onReadPixels(
const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
- flushPending();
+ this->flushPending();
return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
x, y, config8888);
}