diff options
author | 2012-02-13 21:53:45 +0000 | |
---|---|---|
committer | 2012-02-13 21:53:45 +0000 | |
commit | 8f9ecbd3466d4330886b4c23b06e75b468c795ad (patch) | |
tree | f80694e771c12c45d9c738b879ab3e379f61f148 /src | |
parent | 813d38b7a07957f2990ccca52ddab55fe0b1c632 (diff) |
Adding API and unit testing for deferred canvas clearing/purging
REVIEW=http://codereview.appspot.com/5646057/
TEST=DeferredCanvas unit test
git-svn-id: http://skia.googlecode.com/svn/trunk@3181 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkPictureRecord.cpp | 14 | ||||
-rw-r--r-- | src/core/SkPictureRecord.h | 5 | ||||
-rw-r--r-- | src/utils/SkDeferredCanvas.cpp | 88 |
3 files changed, 70 insertions, 37 deletions
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index f31065b444..c56c104ebe 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -23,6 +23,7 @@ SkPictureRecord::SkPictureRecord(uint32_t flags) : fRestoreOffsetStack.push(0); fPathHeap = NULL; // lazy allocate + fFirstSavedLayerIndex = kNoSavedLayerIndex; } SkPictureRecord::~SkPictureRecord() { @@ -50,6 +51,10 @@ int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint, fRestoreOffsetStack.push(0); + if (kNoSavedLayerIndex == fFirstSavedLayerIndex) { + fFirstSavedLayerIndex = fRestoreOffsetStack.count(); + } + validate(); /* Don't actually call saveLayer, because that will try to allocate an offscreen device (potentially very big) which we don't actually need @@ -60,6 +65,10 @@ int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint, return this->INHERITED::save(flags); } +bool SkPictureRecord::isDrawingToLayer() const { + return fFirstSavedLayerIndex != kNoSavedLayerIndex; +} + void SkPictureRecord::restore() { // check for underflow if (fRestoreOffsetStack.count() == 0) { @@ -74,6 +83,11 @@ void SkPictureRecord::restore() { offset = *peek; *peek = restoreOffset; } + + if (fRestoreOffsetStack.count() == fFirstSavedLayerIndex) { + fFirstSavedLayerIndex = kNoSavedLayerIndex; + } + fRestoreOffsetStack.pop(); addDraw(RESTORE); diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h index ff6585d375..e8fa370f9d 100644 --- a/src/core/SkPictureRecord.h +++ b/src/core/SkPictureRecord.h @@ -65,6 +65,7 @@ public: const uint16_t indices[], int indexCount, const SkPaint&) SK_OVERRIDE; virtual void drawData(const void*, size_t) SK_OVERRIDE; + virtual bool isDrawingToLayer() const SK_OVERRIDE; void addFontMetricsTopBottom(const SkPaint& paint, SkScalar minY, SkScalar maxY); @@ -92,6 +93,10 @@ public: private: SkTDArray<uint32_t> fRestoreOffsetStack; + int fFirstSavedLayerIndex; + enum { + kNoSavedLayerIndex = -1 + }; void addDraw(DrawType drawType) { #ifdef SK_DEBUG_TRACE diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp index 6988517fe6..27fc0c5901 100644 --- a/src/utils/SkDeferredCanvas.cpp +++ b/src/utils/SkDeferredCanvas.cpp @@ -288,7 +288,7 @@ void SkDeferredCanvas::clear(SkColor color) { // purge pending commands if (fDeferredDrawing) { - getDeferredDevice()->purgePending(); + getDeferredDevice()->contentsCleared(); } drawingCanvas()->clear(color); @@ -297,7 +297,7 @@ void SkDeferredCanvas::clear(SkColor color) void SkDeferredCanvas::drawPaint(const SkPaint& paint) { if (fDeferredDrawing && isFullFrame(NULL, &paint) && isPaintOpaque(paint)) { - getDeferredDevice()->purgePending(); + getDeferredDevice()->contentsCleared(); } drawingCanvas()->drawPaint(paint); @@ -312,7 +312,7 @@ void SkDeferredCanvas::drawPoints(PointMode mode, size_t count, void SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { if (fDeferredDrawing && isFullFrame(&rect, &paint) && isPaintOpaque(paint)) { - getDeferredDevice()->purgePending(); + getDeferredDevice()->contentsCleared(); } drawingCanvas()->drawRect(rect, paint); @@ -326,12 +326,12 @@ void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) void SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint) { - SkRect bitmapRect = SkRect::MakeXYWH(left, top, bitmap.width(), - bitmap.height()); + SkRect bitmapRect = SkRect::MakeXYWH(left, top, + SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); if (fDeferredDrawing && isFullFrame(&bitmapRect, paint) && isPaintOpaque(*paint, &bitmap)) { - getDeferredDevice()->purgePending(); + getDeferredDevice()->contentsCleared(); } drawingCanvas()->drawBitmap(bitmap, left, top, paint); @@ -345,7 +345,7 @@ void SkDeferredCanvas::drawBitmapRect(const SkBitmap& bitmap, if (fDeferredDrawing && isFullFrame(&dst, paint) && isPaintOpaque(*paint, &bitmap)) { - getDeferredDevice()->purgePending(); + getDeferredDevice()->contentsCleared(); } drawingCanvas()->drawBitmapRect(bitmap, src, @@ -378,12 +378,15 @@ void SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap, void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { - SkRect bitmapRect = SkRect::MakeXYWH(left, top, bitmap.width(), - bitmap.height()); + SkRect bitmapRect = SkRect::MakeXYWH( + SkIntToScalar(left), + SkIntToScalar(top), + SkIntToScalar(bitmap.width()), + SkIntToScalar(bitmap.height())); if (fDeferredDrawing && isFullFrame(&bitmapRect, paint) && isPaintOpaque(*paint, &bitmap)) { - getDeferredDevice()->purgePending(); + getDeferredDevice()->contentsCleared(); } drawingCanvas()->drawSprite(bitmap, left, top, @@ -466,6 +469,7 @@ SkDeferredCanvas::DeferredDevice::DeferredDevice( SkDevice* immediateDevice, DeviceContext* deviceContext) : SkDevice(SkBitmap::kNo_Config, immediateDevice->width(), immediateDevice->height(), immediateDevice->isOpaque()) + , fFreshFrame(true) { fDeviceContext = deviceContext; SkSafeRef(fDeviceContext); @@ -474,7 +478,6 @@ SkDeferredCanvas::DeferredDevice::DeferredDevice( fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(), fImmediateDevice->height(), SkPicture::kUsePathBoundsForClip_RecordingFlag); - fBitmapInitialized = false; } SkDeferredCanvas::DeferredDevice::~DeferredDevice() @@ -489,38 +492,49 @@ void SkDeferredCanvas::DeferredDevice::setDeviceContext( SkRefCnt_SafeAssign(fDeviceContext, deviceContext); } -void SkDeferredCanvas::DeferredDevice::purgePending() +void SkDeferredCanvas::DeferredDevice::contentsCleared() { - // TODO: find a way to transfer the state stack and layers - // to the new recording canvas. For now, purge only works - // with an empty stack. - if (fRecordingCanvas->getSaveCount() > 1) - return; + if (!fRecordingCanvas->isDrawingToLayer()) { + fFreshFrame = true; - // Save state that is trashed by the purge - SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter(); - SkSafeRef(drawFilter); // So that it survives the purge - SkMatrix matrix = fRecordingCanvas->getTotalMatrix(); - SkRegion clipRegion = fRecordingCanvas->getTotalClip(); + // 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) { - // beginRecording creates a new recording canvas and discards the old one, - // hence purging deferred draw ops. - fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(), - fImmediateDevice->height(), - SkPicture::kUsePathBoundsForClip_RecordingFlag); + // Save state that is trashed by the purge + SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter(); + SkSafeRef(drawFilter); // So that it survives the purge + SkMatrix matrix = fRecordingCanvas->getTotalMatrix(); + SkRegion clipRegion = fRecordingCanvas->getTotalClip(); - // Restore pre-purge state - if (!clipRegion.isEmpty()) { - fRecordingCanvas->clipRegion(clipRegion, SkRegion::kReplace_Op); - } - if (!matrix.isIdentity()) { - fRecordingCanvas->setMatrix(matrix); - } - if (drawFilter) { - fRecordingCanvas->setDrawFilter(drawFilter)->unref(); + // beginRecording creates a new recording canvas and discards the + // old one, hence purging deferred draw ops. + fRecordingCanvas = fPicture.beginRecording( + fImmediateDevice->width(), + fImmediateDevice->height(), + SkPicture::kUsePathBoundsForClip_RecordingFlag); + + // Restore pre-purge state + if (!clipRegion.isEmpty()) { + fRecordingCanvas->clipRegion(clipRegion, SkRegion::kReplace_Op); + } + if (!matrix.isIdentity()) { + fRecordingCanvas->setMatrix(matrix); + } + if (drawFilter) { + fRecordingCanvas->setDrawFilter(drawFilter)->unref(); + } + } } } +bool SkDeferredCanvas::DeferredDevice::isFreshFrame() { + bool ret = fFreshFrame; + fFreshFrame = false; + return ret; +} + void SkDeferredCanvas::DeferredDevice::flushPending() { if (fDeviceContext) { @@ -576,7 +590,7 @@ void SkDeferredCanvas::DeferredDevice::writePixels(const SkBitmap& bitmap, { if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() && (y + bitmap.height()) >= height()) { - purgePending(); + contentsCleared(); } if (SkBitmap::kARGB_8888_Config == bitmap.config() && |