aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-13 21:53:45 +0000
committerGravatar junov@chromium.org <junov@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-02-13 21:53:45 +0000
commit8f9ecbd3466d4330886b4c23b06e75b468c795ad (patch)
treef80694e771c12c45d9c738b879ab3e379f61f148 /src
parent813d38b7a07957f2990ccca52ddab55fe0b1c632 (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.cpp14
-rw-r--r--src/core/SkPictureRecord.h5
-rw-r--r--src/utils/SkDeferredCanvas.cpp88
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() &&