Index: src/core/SkPicturePlayback.cpp |
=================================================================== |
--- src/core/SkPicturePlayback.cpp (revision 13686) |
+++ src/core/SkPicturePlayback.cpp (working copy) |
@@ -5,15 +5,16 @@ |
* Use of this source code is governed by a BSD-style license that can be |
* found in the LICENSE file. |
*/ |
+#include <new> |
+#include "SkBBoxHierarchy.h" |
+#include "SkOffsetTable.h" |
#include "SkPicturePlayback.h" |
#include "SkPictureRecord.h" |
+#include "SkPictureStateTree.h" |
+#include "SkReadBuffer.h" |
#include "SkTypeface.h" |
-#include "SkReadBuffer.h" |
+#include "SkTSort.h" |
#include "SkWriteBuffer.h" |
-#include <new> |
-#include "SkBBoxHierarchy.h" |
-#include "SkPictureStateTree.h" |
-#include "SkTSort.h" |
template <typename T> int SafeCount(const T* obj) { |
return obj ? obj->count() : 0; |
@@ -101,6 +102,8 @@ |
fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap)); |
fPathHeap.reset(SkSafeRef(record.fPathHeap)); |
+ fBitmapUseOffsets.reset(SkSafeRef(record.fBitmapUseOffsets.get())); |
+ |
// ensure that the paths bounds are pre-computed |
if (fPathHeap.get()) { |
for (int i = 0; i < fPathHeap->count(); i++) { |
@@ -718,6 +721,50 @@ |
return (DrawType) op; |
} |
+// The activeOps parameter is actually "const SkTDArray<SkPictureStateTree::Draw*>&". |
+// It represents the operations about to be drawn, as generated by some spatial |
+// subdivision helper class. It should already be in 'fOffset' sorted order. |
+void SkPicturePlayback::preLoadBitmaps(const SkTDArray<void*>& activeOps) { |
+ if (0 == activeOps.count() || NULL == fBitmapUseOffsets) { |
+ return; |
+ } |
+ |
+ SkTDArray<int> active; |
+ |
+ SkAutoTDeleteArray<bool> needToCheck(new bool[fBitmapUseOffsets->numIDs()]); |
+ for (int i = 0; i < fBitmapUseOffsets->numIDs(); ++i) { |
+ needToCheck.get()[i] = true; |
+ } |
+ |
+ uint32_t max = ((SkPictureStateTree::Draw*)activeOps[activeOps.count()-1])->fOffset; |
+ |
+ for (int i = 0; i < activeOps.count(); ++i) { |
+ SkPictureStateTree::Draw* draw = (SkPictureStateTree::Draw*) activeOps[i]; |
+ |
+ for (int j = 0; j < fBitmapUseOffsets->numIDs(); ++j) { |
+ if (!needToCheck.get()[j]) { |
+ continue; |
+ } |
+ |
+ if (!fBitmapUseOffsets->overlap(j, draw->fOffset, max)) { |
+ needToCheck.get()[j] = false; |
+ continue; |
+ } |
+ |
+ if (!fBitmapUseOffsets->includes(j, draw->fOffset)) { |
+ continue; |
+ } |
+ |
+ *active.append() = j; |
+ needToCheck.get()[j] = false; |
+ } |
+ } |
+ |
+ for (int i = 0; i < active.count(); ++i) { |
+ SkDebugf("preload texture %d\n", active[i]); |
+ } |
+} |
+ |
void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) { |
#ifdef ENABLE_TIME_DRAW |
SkAutoTime at("SkPicture::draw", 50); |
@@ -738,26 +785,26 @@ |
SkReader32 reader(fOpData->bytes(), fOpData->size()); |
TextContainer text; |
- SkTDArray<void*> results; |
+ SkTDArray<void*> activeOps; |
if (NULL != fStateTree && NULL != fBoundingHierarchy) { |
SkRect clipBounds; |
if (canvas.getClipBounds(&clipBounds)) { |
SkIRect query; |
clipBounds.roundOut(&query); |
- fBoundingHierarchy->search(query, &results); |
- if (results.count() == 0) { |
+ fBoundingHierarchy->search(query, &activeOps); |
+ if (activeOps.count() == 0) { |
return; |
} |
SkTQSort<SkPictureStateTree::Draw>( |
- reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()), |
- reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1)); |
+ reinterpret_cast<SkPictureStateTree::Draw**>(activeOps.begin()), |
+ reinterpret_cast<SkPictureStateTree::Draw**>(activeOps.end()-1)); |
} |
} |
SkPictureStateTree::Iterator it = (NULL == fStateTree) ? |
SkPictureStateTree::Iterator() : |
- fStateTree->getIterator(results, &canvas); |
+ fStateTree->getIterator(activeOps, &canvas); |
if (it.isValid()) { |
uint32_t skipTo = it.draw(); |
@@ -767,6 +814,8 @@ |
reader.setOffset(skipTo); |
} |
+ this->preLoadBitmaps(activeOps); |
+ |
// Record this, so we can concat w/ it if we encounter a setMatrix() |
SkMatrix initialMatrix = canvas.getTotalMatrix(); |
int originalSaveCount = canvas.getSaveCount(); |