From 70512af9dd7a6b2c0a3f5971fd6e103dc577a400 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Tue, 18 Mar 2014 17:45:32 +0000 Subject: Add a means of extracting active operations from SkPicture For the "pull forward" task I will be comparing the two cases: analyze the whole skp and use the BBH information analyze only the active portion of the skp In the first case we need a way to get the BBH information out of the picture in order to extract the relevant portions of the whole-skp analysis. This adds caching of the active ops so that work isn't duplicated between when the optimization path queries for that information and when the usual draw path queries for it. Committed: http://code.google.com/p/skia/source/detail?r=13836 R=reed@google.com, bsalomon@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/195793010 git-svn-id: http://skia.googlecode.com/svn/trunk@13853 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkPicturePlayback.cpp | 78 +++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 16 deletions(-) (limited to 'src/core/SkPicturePlayback.cpp') diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index d61e616c4d..25bc339363 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2011 Google Inc. * @@ -69,7 +68,7 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record, bool deepCop record.validate(record.writeStream().bytesWritten(), 0); const SkWriter32& writer = record.writeStream(); - init(); + this->init(); SkASSERT(!fOpData); if (writer.bytesWritten() == 0) { fOpData = SkData::NewEmpty(); @@ -261,6 +260,7 @@ void SkPicturePlayback::init() { fFactoryPlayback = NULL; fBoundingHierarchy = NULL; fStateTree = NULL; + fCachedActiveOps = NULL; } SkPicturePlayback::~SkPicturePlayback() { @@ -271,6 +271,8 @@ SkPicturePlayback::~SkPicturePlayback() { SkSafeUnref(fBoundingHierarchy); SkSafeUnref(fStateTree); + SkDELETE(fCachedActiveOps); + for (int i = 0; i < fPictureCount; i++) { fPictureRefs[i]->unref(); } @@ -754,8 +756,13 @@ static DrawType read_op_and_size(SkReader32* reader, uint32_t* size) { // The activeOps parameter is actually "const SkTDArray&". // 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& activeOps) { - if (0 == activeOps.count() || NULL == fBitmapUseOffsets) { +void SkPicturePlayback::preLoadBitmaps(const SkTDArray* activeOps) { + if ((NULL != activeOps && 0 == activeOps->count()) || NULL == fBitmapUseOffsets) { + return; + } + + if (NULL == activeOps) { + // going to need everything return; } @@ -766,10 +773,10 @@ void SkPicturePlayback::preLoadBitmaps(const SkTDArray& activeOps) { needToCheck.get()[i] = true; } - uint32_t max = ((SkPictureStateTree::Draw*)activeOps[activeOps.count()-1])->fOffset; + 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 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]) { @@ -795,6 +802,42 @@ void SkPicturePlayback::preLoadBitmaps(const SkTDArray& activeOps) { } } +uint32_t SkPicturePlayback::CachedOperationList::offset(int index) const { + SkASSERT(index < fOps.count()); + return ((SkPictureStateTree::Draw*)fOps[index])->fOffset; +} + +const SkMatrix& SkPicturePlayback::CachedOperationList::matrix(int index) const { + SkASSERT(index < fOps.count()); + return *((SkPictureStateTree::Draw*)fOps[index])->fMatrix; +} + +const SkPicture::OperationList& SkPicturePlayback::getActiveOps(const SkIRect& query) { + if (NULL == fStateTree || NULL == fBoundingHierarchy) { + return SkPicture::OperationList::InvalidList(); + } + + if (NULL == fCachedActiveOps) { + fCachedActiveOps = SkNEW(CachedOperationList); + } + + if (query == fCachedActiveOps->fCacheQueryRect) { + return *fCachedActiveOps; + } + + fCachedActiveOps->fOps.rewind(); + + fBoundingHierarchy->search(query, &(fCachedActiveOps->fOps)); + if (0 != fCachedActiveOps->fOps.count()) { + SkTQSort( + reinterpret_cast(fCachedActiveOps->fOps.begin()), + reinterpret_cast(fCachedActiveOps->fOps.end()-1)); + } + + fCachedActiveOps->fCacheQueryRect = query; + return *fCachedActiveOps; +} + void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) { #ifdef ENABLE_TIME_DRAW SkAutoTime at("SkPicture::draw", 50); @@ -815,26 +858,29 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) SkReader32 reader(fOpData->bytes(), fOpData->size()); TextContainer text; - SkTDArray activeOps; + const SkTDArray* activeOps = NULL; if (NULL != fStateTree && NULL != fBoundingHierarchy) { SkRect clipBounds; if (canvas.getClipBounds(&clipBounds)) { SkIRect query; clipBounds.roundOut(&query); - fBoundingHierarchy->search(query, &activeOps); - if (activeOps.count() == 0) { - return; + + const SkPicture::OperationList& activeOpsList = this->getActiveOps(query); + if (activeOpsList.valid()) { + if (0 == activeOpsList.numOps()) { + return; // nothing to draw + } + + // Since the opList is valid we know it is our derived class + activeOps = &((const CachedOperationList&)activeOpsList).fOps; } - SkTQSort( - reinterpret_cast(activeOps.begin()), - reinterpret_cast(activeOps.end()-1)); } } - SkPictureStateTree::Iterator it = (NULL == fStateTree) ? + SkPictureStateTree::Iterator it = (NULL == activeOps) ? SkPictureStateTree::Iterator() : - fStateTree->getIterator(activeOps, &canvas); + fStateTree->getIterator(*activeOps, &canvas); if (it.isValid()) { uint32_t skipTo = it.draw(); -- cgit v1.2.3