aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-04-08 23:31:35 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-04-08 23:31:35 +0000
commit506db0b7d2905c6bedba9fc5d4aeaf231a9a34ea (patch)
tree77d73de439e9102d45891be433c5556ee23ce74c /src
parent9ffa52d98fc216b6766f33ffd0d9f1c3a1acdb2f (diff)
SkRecord: make culling work if SkRecordAnnotateCullingPairs is called.
- Allow stateful functors; allow visit()/mutate() at a given index; add count(). - Annotate cull push/pop pairs on the PushCull records. (tested) - Use those annotations to skip ahead in SkRecordDraw. (not yet tested beyond dm --skr) - Make SkRecordDraw a function, move its implementation to a .cpp. BUG=skia:2378 R=fmalita@chromium.org, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/229523002 git-svn-id: http://skia.googlecode.com/svn/trunk@14101 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/record/SkRecord.h42
-rw-r--r--src/record/SkRecordCulling.cpp38
-rw-r--r--src/record/SkRecordCulling.h9
-rw-r--r--src/record/SkRecordDraw.cpp78
-rw-r--r--src/record/SkRecordDraw.h59
-rw-r--r--src/record/SkRecorder.cpp2
-rw-r--r--src/record/SkRecords.h3
7 files changed, 159 insertions, 72 deletions
diff --git a/src/record/SkRecord.h b/src/record/SkRecord.h
index 4013874677..0fe79189d4 100644
--- a/src/record/SkRecord.h
+++ b/src/record/SkRecord.h
@@ -21,33 +21,49 @@ class SkRecord : SkNoncopyable {
public:
SkRecord(size_t chunkBytes = 4096, unsigned firstReserveCount = 64 / sizeof(void*))
: fAlloc(chunkBytes), fCount(0), fReserved(0), kFirstReserveCount(firstReserveCount) {}
- ~SkRecord() { this->mutate(Destroyer()); }
+
+ ~SkRecord() {
+ Destroyer destroyer;
+ this->mutate(destroyer);
+ }
+
+ unsigned count() const { return fCount; }
// Accepts a visitor functor with this interface:
// template <typename T>
- // void operator()()(const T& record) { ... }
+ // void operator()(const T& record) { ... }
// This operator() must be defined for at least all SkRecords::*; your compiler will help you
// get this right.
- //
- // f will be called on each recorded canvas call in the order they were append()ed.
template <typename F>
- void visit(F f) const {
+ void visit(unsigned i, F& f) const {
+ SkASSERT(i < this->count());
+ fRecords[i].visit(fTypes[i], f);
+ }
+
+ // As above. f will be called on each recorded canvas call in the order they were append()ed.
+ template <typename F>
+ void visit(F& f) const {
for (unsigned i = 0; i < fCount; i++) {
- fRecords[i].visit(fTypes[i], f);
+ this->visit(i, f);
}
}
// Accepts a visitor functor with this interface:
// template <typename T>
- // void operator()()(T* record) { ... }
+ // void operator()(T* record) { ... }
// This operator() must be defined for at least all SkRecords::*; again, your compiler will help
// you get this right.
- //
- // f will be called on each recorded canvas call in the order they were append()ed.
template <typename F>
- void mutate(F f) {
+ void mutate(unsigned i, F& f) {
+ SkASSERT(i < this->count());
+ fRecords[i].mutate(fTypes[i], f);
+ }
+
+ // As above. f will be called on each recorded canvas call in the order they were append()ed.
+ template <typename F>
+ void mutate(F& f) {
for (unsigned i = 0; i < fCount; i++) {
- fRecords[i].mutate(fTypes[i], f);
+ this->mutate(i, f);
}
}
@@ -154,7 +170,7 @@ private:
// Visit this record with functor F (see public API above) assuming the record we're
// pointing to has this type.
template <typename F>
- void visit(Type8 type, F f) const {
+ void visit(Type8 type, F& f) const {
#define CASE(T) case SkRecords::T##_Type: return f(*this->ptr<SkRecords::T>());
switch(type) { SK_RECORD_TYPES(CASE) }
#undef CASE
@@ -163,7 +179,7 @@ private:
// Mutate this record with functor F (see public API above) assuming the record we're
// pointing to has this type.
template <typename F>
- void mutate(Type8 type, F f) {
+ void mutate(Type8 type, F& f) {
#define CASE(T) case SkRecords::T##_Type: return f(this->ptr<SkRecords::T>());
switch(type) { SK_RECORD_TYPES(CASE) }
#undef CASE
diff --git a/src/record/SkRecordCulling.cpp b/src/record/SkRecordCulling.cpp
new file mode 100644
index 0000000000..e866bd82cb
--- /dev/null
+++ b/src/record/SkRecordCulling.cpp
@@ -0,0 +1,38 @@
+#include "SkRecordCulling.h"
+
+#include "SkRecords.h"
+#include "SkTDArray.h"
+
+namespace {
+
+struct Annotator {
+ unsigned index;
+ SkTDArray<SkRecords::PushCull*> pushStack;
+
+ // Do nothing to most record types.
+ template <typename T> void operator()(T*) {}
+};
+
+template <> void Annotator::operator()(SkRecords::PushCull* push) {
+ // Store the push's index for now. We'll calculate the offset using this in the paired pop.
+ push->popOffset = index;
+ pushStack.push(push);
+}
+
+template <> void Annotator::operator()(SkRecords::PopCull* pop) {
+ SkRecords::PushCull* push = pushStack.top();
+ pushStack.pop();
+
+ SkASSERT(index > push->popOffset); // push->popOffset holds the index of the push.
+ push->popOffset = index - push->popOffset; // Now it's the offset between push and pop.
+}
+
+} // namespace
+
+void SkRecordAnnotateCullingPairs(SkRecord* record) {
+ Annotator annotator;
+
+ for (annotator.index = 0; annotator.index < record->count(); annotator.index++) {
+ record->mutate(annotator.index, annotator);
+ }
+}
diff --git a/src/record/SkRecordCulling.h b/src/record/SkRecordCulling.h
new file mode 100644
index 0000000000..b8ed88c637
--- /dev/null
+++ b/src/record/SkRecordCulling.h
@@ -0,0 +1,9 @@
+#ifndef SkRecordCulling_DEFINED
+#define SkRecordCulling_DEFINED
+
+#include "SkRecord.h"
+
+// Annotates PushCull records in record with the relative offset of their paired PopCull.
+void SkRecordAnnotateCullingPairs(SkRecord* record);
+
+#endif//SkRecordCulling_DEFINED
diff --git a/src/record/SkRecordDraw.cpp b/src/record/SkRecordDraw.cpp
new file mode 100644
index 0000000000..66b48a3559
--- /dev/null
+++ b/src/record/SkRecordDraw.cpp
@@ -0,0 +1,78 @@
+#include "SkRecordDraw.h"
+
+namespace {
+
+// This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
+struct Draw {
+ unsigned index;
+ SkCanvas* canvas;
+
+ // No base case, so we'll be compile-time checked that we implemented all possibilities below.
+ template <typename T> void operator()(const T&);
+};
+
+template <> void Draw::operator()(const SkRecords::PushCull& pushCull) {
+ if (pushCull.popOffset != SkRecords::kUnsetPopOffset &&
+ canvas->quickReject(pushCull.rect)) {
+ // We skip to the popCull, then the loop moves us just beyond it.
+ index += pushCull.popOffset;
+ } else {
+ canvas->pushCull(pushCull.rect);
+ }
+}
+
+// Nothing fancy below here.
+
+#define CASE(T) template <> void Draw::operator()(const SkRecords::T& r)
+
+CASE(Restore) { canvas->restore(); }
+CASE(Save) { canvas->save(r.flags); }
+CASE(SaveLayer) { canvas->saveLayer(r.bounds, r.paint, r.flags); }
+
+CASE(PopCull) { canvas->popCull(); }
+
+CASE(Concat) { canvas->concat(r.matrix); }
+CASE(SetMatrix) { canvas->setMatrix(r.matrix); }
+
+CASE(ClipPath) { canvas->clipPath(r.path, r.op, r.doAA); }
+CASE(ClipRRect) { canvas->clipRRect(r.rrect, r.op, r.doAA); }
+CASE(ClipRect) { canvas->clipRect(r.rect, r.op, r.doAA); }
+CASE(ClipRegion) { canvas->clipRegion(r.region, r.op); }
+
+CASE(Clear) { canvas->clear(r.color); }
+CASE(DrawBitmap) { canvas->drawBitmap(r.bitmap, r.left, r.top, r.paint); }
+CASE(DrawBitmapMatrix) { canvas->drawBitmapMatrix(r.bitmap, r.matrix, r.paint); }
+CASE(DrawBitmapNine) { canvas->drawBitmapNine(r.bitmap, r.center, r.dst, r.paint); }
+CASE(DrawBitmapRectToRect) {
+ canvas->drawBitmapRectToRect(r.bitmap, r.src, r.dst, r.paint, r.flags);
+}
+CASE(DrawDRRect) { canvas->drawDRRect(r.outer, r.inner, r.paint); }
+CASE(DrawOval) { canvas->drawOval(r.oval, r.paint); }
+CASE(DrawPaint) { canvas->drawPaint(r.paint); }
+CASE(DrawPath) { canvas->drawPath(r.path, r.paint); }
+CASE(DrawPoints) { canvas->drawPoints(r.mode, r.count, r.pts, r.paint); }
+CASE(DrawPosText) { canvas->drawPosText(r.text, r.byteLength, r.pos, r.paint); }
+CASE(DrawPosTextH) { canvas->drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint); }
+CASE(DrawRRect) { canvas->drawRRect(r.rrect, r.paint); }
+CASE(DrawRect) { canvas->drawRect(r.rect, r.paint); }
+CASE(DrawSprite) { canvas->drawSprite(r.bitmap, r.left, r.top, r.paint); }
+CASE(DrawText) { canvas->drawText(r.text, r.byteLength, r.x, r.y, r.paint); }
+CASE(DrawTextOnPath) { canvas->drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint); }
+CASE(DrawVertices) {
+ canvas->drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
+ r.xmode.get(), r.indices, r.indexCount, r.paint);
+}
+#undef CASE
+
+} // namespace
+
+void SkRecordDraw(const SkRecord& record, SkCanvas* canvas) {
+ Draw draw;
+ draw.canvas = canvas;
+
+ for (draw.index = 0; draw.index < record.count(); draw.index++) {
+ record.visit(draw.index, draw);
+ }
+}
+
+
diff --git a/src/record/SkRecordDraw.h b/src/record/SkRecordDraw.h
index 042147df99..684cc1b2e5 100644
--- a/src/record/SkRecordDraw.h
+++ b/src/record/SkRecordDraw.h
@@ -2,64 +2,9 @@
#define SkRecordDraw_DEFINED
#include "SkRecord.h"
-#include "SkRecords.h"
#include "SkCanvas.h"
-// This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
-
-struct SkRecordDraw {
- explicit SkRecordDraw(SkCanvas* canvas) : canvas(canvas) {}
-
- // No base case, so we'll be compile-time checked that we implemented all possibilities below.
- template <typename T> void operator()(const T& record);
-
- SkCanvas* canvas;
-};
-
-// Nothing fancy here.
-// The structs in SkRecord are completely isomorphic to their corresponding SkCanvas calls.
-
-#define CASE(T) template <> void SkRecordDraw::operator()(const SkRecords::T& r)
-
-CASE(Restore) { canvas->restore(); }
-CASE(Save) { canvas->save(r.flags); }
-CASE(SaveLayer) { canvas->saveLayer(r.bounds, r.paint, r.flags); }
-
-CASE(PushCull) { canvas->pushCull(r.rect); }
-CASE(PopCull) { canvas->popCull(); }
-
-CASE(Concat) { canvas->concat(r.matrix); }
-CASE(SetMatrix) { canvas->setMatrix(r.matrix); }
-
-CASE(ClipPath) { canvas->clipPath(r.path, r.op, r.doAA); }
-CASE(ClipRRect) { canvas->clipRRect(r.rrect, r.op, r.doAA); }
-CASE(ClipRect) { canvas->clipRect(r.rect, r.op, r.doAA); }
-CASE(ClipRegion) { canvas->clipRegion(r.region, r.op); }
-
-CASE(Clear) { canvas->clear(r.color); }
-CASE(DrawBitmap) { canvas->drawBitmap(r.bitmap, r.left, r.top, r.paint); }
-CASE(DrawBitmapMatrix) { canvas->drawBitmapMatrix(r.bitmap, r.matrix, r.paint); }
-CASE(DrawBitmapNine) { canvas->drawBitmapNine(r.bitmap, r.center, r.dst, r.paint); }
-CASE(DrawBitmapRectToRect) {
- canvas->drawBitmapRectToRect(r.bitmap, r.src, r.dst, r.paint, r.flags);
-}
-CASE(DrawDRRect) { canvas->drawDRRect(r.outer, r.inner, r.paint); }
-CASE(DrawOval) { canvas->drawOval(r.oval, r.paint); }
-CASE(DrawPaint) { canvas->drawPaint(r.paint); }
-CASE(DrawPath) { canvas->drawPath(r.path, r.paint); }
-CASE(DrawPoints) { canvas->drawPoints(r.mode, r.count, r.pts, r.paint); }
-CASE(DrawPosText) { canvas->drawPosText(r.text, r.byteLength, r.pos, r.paint); }
-CASE(DrawPosTextH) { canvas->drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint); }
-CASE(DrawRRect) { canvas->drawRRect(r.rrect, r.paint); }
-CASE(DrawRect) { canvas->drawRect(r.rect, r.paint); }
-CASE(DrawSprite) { canvas->drawSprite(r.bitmap, r.left, r.top, r.paint); }
-CASE(DrawText) { canvas->drawText(r.text, r.byteLength, r.x, r.y, r.paint); }
-CASE(DrawTextOnPath) { canvas->drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint); }
-CASE(DrawVertices) {
- canvas->drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
- r.xmode.get(), r.indices, r.indexCount, r.paint);
-}
-
-#undef CASE
+// Draw an SkRecord into an SkCanvas.
+void SkRecordDraw(const SkRecord&, SkCanvas*);
#endif//SkRecordDraw_DEFINED
diff --git a/src/record/SkRecorder.cpp b/src/record/SkRecorder.cpp
index fabb4be861..cba5f74f8f 100644
--- a/src/record/SkRecorder.cpp
+++ b/src/record/SkRecorder.cpp
@@ -196,7 +196,7 @@ void SkRecorder::willRestore() {
}
void SkRecorder::onPushCull(const SkRect& rect) {
- APPEND(PushCull, rect);
+ APPEND(PushCull, rect, SkRecords::kUnsetPopOffset);
}
void SkRecorder::onPopCull() {
diff --git a/src/record/SkRecords.h b/src/record/SkRecords.h
index 17a8e849ad..961728af41 100644
--- a/src/record/SkRecords.h
+++ b/src/record/SkRecords.h
@@ -127,7 +127,8 @@ RECORD0(Restore);
RECORD1(Save, SkCanvas::SaveFlags, flags);
RECORD3(SaveLayer, SkRect*, bounds, SkPaint*, paint, SkCanvas::SaveFlags, flags);
-RECORD1(PushCull, SkRect, rect);
+static const unsigned kUnsetPopOffset = 0;
+RECORD2(PushCull, SkRect, rect, unsigned, popOffset);
RECORD0(PopCull);
RECORD1(Concat, SkMatrix, matrix);