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
This commit is contained in:
junov@chromium.org 2012-08-15 19:49:22 +00:00
parent 837d31a0c9
commit a8db8fe39a
3 changed files with 22 additions and 10 deletions

View File

@ -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;
};

View File

@ -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;

View File

@ -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();