Adding optimization to avoid image copy in SkSurface copy on write when content is discardable
This patch also adds code to SkDeferredCanvas to trigger the optimization.
TEST=DeferredSurfaceCopy bench, Surface unit test
R=reed@google.com
Author: junov@chromium.org
Review URL: https://chromiumcodereview.appspot.com/14063015
git-svn-id: http://skia.googlecode.com/svn/trunk@8797 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp
index 42e9537..c181818 100644
--- a/src/utils/SkDeferredCanvas.cpp
+++ b/src/utils/SkDeferredCanvas.cpp
@@ -248,6 +248,7 @@
SkSurface* fSurface;
SkDeferredCanvas::NotificationClient* fNotificationClient;
bool fFreshFrame;
+ bool fCanDiscardCanvasContents;
size_t fMaxRecordingStorageBytes;
size_t fPreviousStorageAllocated;
size_t fBitmapSizeThreshold;
@@ -281,6 +282,7 @@
void DeferredDevice::init() {
fRecordingCanvas = NULL;
fFreshFrame = true;
+ fCanDiscardCanvasContents = false;
fPreviousStorageAllocated = 0;
fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold;
fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
@@ -312,11 +314,14 @@
}
void DeferredDevice::skipPendingCommands() {
- if (!fRecordingCanvas->isDrawingToLayer() && fPipeController.hasPendingCommands()) {
- fFreshFrame = true;
- flushPendingCommands(kSilent_PlaybackMode);
- if (fNotificationClient) {
- fNotificationClient->skippedPendingDrawCommands();
+ if (!fRecordingCanvas->isDrawingToLayer()) {
+ fCanDiscardCanvasContents = true;
+ if (fPipeController.hasPendingCommands()) {
+ fFreshFrame = true;
+ flushPendingCommands(kSilent_PlaybackMode);
+ if (fNotificationClient) {
+ fNotificationClient->skippedPendingDrawCommands();
+ }
}
}
}
@@ -335,8 +340,18 @@
if (!fPipeController.hasPendingCommands()) {
return;
}
- if (playbackMode == kNormal_PlaybackMode && fNotificationClient) {
- fNotificationClient->prepareForDraw();
+ if (playbackMode == kNormal_PlaybackMode) {
+ if (NULL != fNotificationClient) {
+ fNotificationClient->prepareForDraw();
+ }
+ if (fCanDiscardCanvasContents) {
+ if (NULL != fSurface) {
+ // Pre-empt notifyContentChanged(false) calls that will happen
+ // during flush
+ fSurface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
+ }
+ fCanDiscardCanvasContents = false;
+ }
}
fPipeWriter.flushRecording(true);
fPipeController.playback(kSilent_PlaybackMode == playbackMode);