From: junov@chromium.org Date: Wed, 15 Aug 2012 19:49:22 +0000 (+0000) Subject: Fixing a deferred canvas optimization that purges pending draws when the canvas is... X-Git-Tag: submit/tizen/20180928.044319~15160 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a8db8fe39a640bda4b85b9342c3b6b2525142afa;p=platform%2Fupstream%2FlibSkiaSharp.git Fixing a deferred canvas optimization that purges pending draws when the canvas is cleared It appears that the recording canvas returns a save count of 1 when the save stack is empty. In order to pass Canvas unit tests when a clear occurs, changes to SkGPipe were necessary to allow SkDeferredCanvas to set the device bounds on the SkGPipeCanvas. A positive side effect of this change is that graphics primitives that fall outside of the device bounds will now always be culled at the recording stage (as opposed playback). BUG=http://code.google.com/p/skia/issues/detail?id=782 TEST=deferred_canvas_record bench test Review URL: https://codereview.appspot.com/6454157 git-svn-id: http://skia.googlecode.com/svn/trunk@5117 2bbb7eff-a529-9590-31e7-b0007b416f81 --- diff --git a/include/pipe/SkGPipe.h b/include/pipe/SkGPipe.h index 40ab30af7c..bbe504aee6 100644 --- a/include/pipe/SkGPipe.h +++ b/include/pipe/SkGPipe.h @@ -103,7 +103,9 @@ public: kSharedAddressSpace_Flag = 1 << 1 }; - SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0); + SkCanvas* startRecording(SkGPipeController*, uint32_t flags = 0, + uint32_t width = kDefaultRecordingCanvasSize, + uint32_t height = kDefaultRecordingCanvasSize); // called in destructor, but can be called sooner once you know there // should be no more drawing calls made into the recording canvas. @@ -136,6 +138,10 @@ public: size_t freeMemoryIfPossible(size_t bytesToFree); private: + enum { + kDefaultRecordingCanvasSize = 32767, + }; + SkGPipeCanvas* fCanvas; SkWriter32 fWriter; }; diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp index 4f408fd179..aad4c8a9c0 100644 --- a/src/pipe/SkGPipeWrite.cpp +++ b/src/pipe/SkGPipeWrite.cpp @@ -163,7 +163,8 @@ public: class SkGPipeCanvas : public SkCanvas { public: - SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags); + SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags, + uint32_t width, uint32_t height); virtual ~SkGPipeCanvas(); void finish() { @@ -400,7 +401,8 @@ private: #define FLATTENABLES_TO_KEEP 10 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, - SkWriter32* writer, uint32_t flags) + SkWriter32* writer, uint32_t flags, + uint32_t width, uint32_t height) : fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL) , fWriter(*writer) , fFlags(flags) @@ -414,10 +416,9 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex)); // we need a device to limit our clip - // should the caller give us the bounds? // We don't allocate pixels for the bitmap SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767); + bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height); SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap)); this->setDevice(device)->unref(); @@ -1091,10 +1092,11 @@ SkGPipeWriter::~SkGPipeWriter() { this->endRecording(); } -SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) { +SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags, + uint32_t width, uint32_t height) { if (NULL == fCanvas) { fWriter.reset(NULL, 0); - fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags)); + fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags, width, height)); } controller->setCanvas(fCanvas); return fCanvas; diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp index bf3ce168da..c66e09cfae 100644 --- a/src/utils/SkDeferredCanvas.cpp +++ b/src/utils/SkDeferredCanvas.cpp @@ -348,6 +348,7 @@ DeferredDevice::DeferredDevice( SkDevice* immediateDevice, SkDeferredCanvas::NotificationClient* notificationClient) : SkDevice(SkBitmap::kNo_Config, immediateDevice->width(), immediateDevice->height(), immediateDevice->isOpaque()) + , fRecordingCanvas(NULL) , fFreshFrame(true) , fPreviousStorageAllocated(0){ @@ -378,7 +379,9 @@ void DeferredDevice::endRecording() { } void DeferredDevice::beginRecording() { - fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0); + SkASSERT(NULL == fRecordingCanvas); + fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0, + fImmediateDevice->width(), fImmediateDevice->height()); } void DeferredDevice::setNotificationClient( @@ -392,8 +395,9 @@ void DeferredDevice::contentsCleared() { // TODO: find a way to transfer the state stack and layers // to the new recording canvas. For now, purging only works - // with an empty stack. - if (fRecordingCanvas->getSaveCount() == 0) { + // with an empty stack. A save count of 1 means an empty stack. + SkASSERT(fRecordingCanvas->getSaveCount() >= 1); + if (fRecordingCanvas->getSaveCount() == 1) { // Save state that is trashed by the purge SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter();