Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(457)

Side by Side Diff: src/core/SkPicturePlayback.cpp

Issue 378343002: Refactor SkPicturePlayback for SkPictureReplacementPlayback (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Move StepIterator to be next to SkipIterTo Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkPicturePlayback.h ('k') | src/core/SkPictureStateTree.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCanvas.h" 8 #include "SkCanvas.h"
9 #include "SkPictureData.h" 9 #include "SkPictureData.h"
10 #include "SkPicturePlayback.h" 10 #include "SkPicturePlayback.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 void get_text(SkReader32* reader, TextContainer* text) { 99 void get_text(SkReader32* reader, TextContainer* text) {
100 size_t length = text->fByteLength = reader->readInt(); 100 size_t length = text->fByteLength = reader->readInt();
101 text->fText = (const char*)reader->skip(length); 101 text->fText = (const char*)reader->skip(length);
102 } 102 }
103 103
104 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multip le threads. 104 // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multip le threads.
105 static SkBitmap shallow_copy(const SkBitmap& bitmap) { 105 static SkBitmap shallow_copy(const SkBitmap& bitmap) {
106 return bitmap; 106 return bitmap;
107 } 107 }
108 108
109 void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) { 109 const SkPicture::OperationList* SkPicturePlayback::getActiveOps(const SkCanvas* canvas) {
110 AutoResetOpID aroi(this);
111 SkASSERT(0 == fCurOffset);
112
113 // kDrawComplete will be the signal that we have reached the end of
114 // the command stream
115 static const uint32_t kDrawComplete = SK_MaxU32;
116
117 SkReader32 reader(fPictureData->fOpData->bytes(), fPictureData->fOpData->siz e());
118 SkAutoTDelete<const SkPicture::OperationList> activeOpsList;
119 const SkTDArray<void*>* activeOps = NULL;
120 110
121 if (fUseBBH && NULL != fPictureData->fStateTree && NULL != fPictureData->fBo undingHierarchy) { 111 if (fUseBBH && NULL != fPictureData->fStateTree && NULL != fPictureData->fBo undingHierarchy) {
122 SkRect clipBounds; 112 SkRect clipBounds;
123 if (canvas->getClipBounds(&clipBounds)) { 113 if (canvas->getClipBounds(&clipBounds)) {
124 SkIRect query; 114 SkIRect query;
125 clipBounds.roundOut(&query); 115 clipBounds.roundOut(&query);
126 116
127 activeOpsList.reset(fPictureData->getActiveOps(query)); 117 return fPictureData->getActiveOps(query);
128 if (NULL != activeOpsList.get()) { 118 }
129 if (0 == activeOpsList->numOps()) { 119 }
130 return; // nothing to draw 120
121 return NULL;
122 }
123
124 // Initialize the state tree iterator. Return false if there is nothing left to draw.
125 bool SkPicturePlayback::initIterator(SkPictureStateTree::Iterator* iter,
126 SkCanvas* canvas,
127 const SkPicture::OperationList *activeOpsLi st) {
128
129 if (NULL != activeOpsList) {
130 if (0 == activeOpsList->numOps()) {
131 return false; // nothing to draw
132 }
133
134 fPictureData->fStateTree->initIterator(iter, activeOpsList->fOps, canvas );
135 }
136
137 return true;
138 }
139
140 bool SkPicturePlayback::replaceOps(SkPictureStateTree::Iterator* iter,
141 SkReader32* reader,
142 SkCanvas* canvas,
143 const SkMatrix& initialMatrix) {
144 if (NULL != fReplacements) {
145 // Potentially replace a block of operations with a single drawBitmap ca ll
146 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp =
147 fReplacements->lookupByStart(reader- >offset());
148 if (NULL != temp) {
149 SkASSERT(NULL != temp->fBM);
150 SkASSERT(NULL != temp->fPaint);
151 canvas->save();
152 canvas->setMatrix(initialMatrix);
153 SkRect src = SkRect::Make(temp->fSrcRect);
154 SkRect dst = SkRect::MakeXYWH(temp->fPos.fX, temp->fPos.fY,
155 temp->fSrcRect.width(),
156 temp->fSrcRect.height());
157 canvas->drawBitmapRectToRect(*temp->fBM, &src, dst, temp->fPaint);
158 canvas->restore();
159
160 if (iter->isValid()) {
161 // This save is needed since the BBH will automatically issue
162 // a restore to balanced the saveLayer we're skipping
163 canvas->save();
164
165 // At this point we know that the PictureStateTree was aiming
166 // for some draw op within temp's saveLayer (although potentiall y
167 // in a separate saveLayer nested inside it).
168 // We need to skip all the operations inside temp's range
169 // along with all the associated state changes but update
170 // the state tree to the first operation outside temp's range.
171
172 uint32_t skipTo;
173 do {
174 skipTo = iter->nextDraw();
175 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
176 break;
177 }
178
179 if (skipTo <= temp->fStop) {
180 reader->setOffset(skipTo);
181 uint32_t size;
182 DrawType op = ReadOpAndSize(reader, &size);
183 // Since we are relying on the normal SkPictureStateTree
184 // playback we need to convert any nested saveLayer call s
185 // it may issue into saves (so that all its internal
186 // restores will be balanced).
187 if (SAVE_LAYER == op) {
188 canvas->save();
189 }
190 }
191 } while (skipTo <= temp->fStop);
192
193 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
194 reader->setOffset(reader->size()); // skip to end
195 return true;
131 } 196 }
132 197
133 activeOps = &(activeOpsList.get()->fOps); 198 reader->setOffset(skipTo);
199 } else {
200 reader->setOffset(temp->fStop);
201 uint32_t size;
202 SkDEBUGCODE(DrawType op = ) ReadOpAndSize(reader, &size);
203 SkASSERT(RESTORE == op);
134 } 204 }
205
206 return true;
135 } 207 }
136 } 208 }
137 209
138 SkPictureStateTree::Iterator it = (NULL == activeOps) ? 210 return false;
139 SkPictureStateTree::Iterator() : 211 }
140 fPictureData->fStateTree->getIterator(*activeOps, canvas);
141 212
142 if (it.isValid()) { 213 // If 'iter' is valid use it to skip forward through the picture.
143 uint32_t skipTo = it.nextDraw(); 214 void SkPicturePlayback::StepIterator(SkPictureStateTree::Iterator* iter, SkReade r32* reader) {
144 if (kDrawComplete == skipTo) { 215 if (iter->isValid()) {
145 return; 216 uint32_t skipTo = iter->nextDraw();
217 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
218 reader->setOffset(reader->size()); // skip to end
219 } else {
220 reader->setOffset(skipTo);
146 } 221 }
147 reader.setOffset(skipTo);
148 } 222 }
223 }
224
225 // Update the iterator and state tree to catch up with the skipped ops.
226 void SkPicturePlayback::SkipIterTo(SkPictureStateTree::Iterator* iter,
227 SkReader32* reader,
228 uint32_t skipTo) {
229 SkASSERT(skipTo <= reader->size());
230 SkASSERT(reader->offset() <= skipTo); // should only be skipping forward
231
232 if (iter->isValid()) {
233 // If using a bounding box hierarchy, advance the state tree
234 // iterator until at or after skipTo
235 uint32_t adjustedSkipTo;
236 do {
237 adjustedSkipTo = iter->nextDraw();
238 } while (adjustedSkipTo < skipTo);
239 skipTo = adjustedSkipTo;
240 }
241 if (SkPictureStateTree::Iterator::kDrawComplete == skipTo) {
242 reader->setOffset(reader->size()); // skip to end
243 } else {
244 reader->setOffset(skipTo);
245 }
246 }
247
248 void SkPicturePlayback::draw(SkCanvas* canvas, SkDrawPictureCallback* callback) {
249 AutoResetOpID aroi(this);
250 SkASSERT(0 == fCurOffset);
251
252 SkAutoTDelete<const SkPicture::OperationList> activeOpsList(this->getActiveO ps(canvas));
253 SkPictureStateTree::Iterator it;
254
255 if (!this->initIterator(&it, canvas, activeOpsList.get())) {
256 return; // nothing to draw
257 }
258
259 SkReader32 reader(fPictureData->opData()->bytes(), fPictureData->opData()->s ize());
260
261 StepIterator(&it, &reader);
149 262
150 // Record this, so we can concat w/ it if we encounter a setMatrix() 263 // Record this, so we can concat w/ it if we encounter a setMatrix()
151 SkMatrix initialMatrix = canvas->getTotalMatrix(); 264 SkMatrix initialMatrix = canvas->getTotalMatrix();
152 265
153 SkAutoCanvasRestore acr(canvas, false); 266 SkAutoCanvasRestore acr(canvas, false);
154 267
155 while (!reader.eof()) { 268 while (!reader.eof()) {
156 if (callback && callback->abortDrawing()) { 269 if (NULL != callback && callback->abortDrawing()) {
157 return; 270 return;
158 } 271 }
159 272
160 if (NULL != fReplacements) { 273 if (this->replaceOps(&it, &reader, canvas, initialMatrix)) {
161 // Potentially replace a block of operations with a single drawBitma p call 274 continue;
162 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp =
163 fReplacements->lookupByStart(reader.offset());
164 if (NULL != temp) {
165 SkASSERT(NULL != temp->fBM);
166 SkASSERT(NULL != temp->fPaint);
167 canvas->save();
168 canvas->setMatrix(initialMatrix);
169 SkRect src = SkRect::Make(temp->fSrcRect);
170 SkRect dst = SkRect::MakeXYWH(temp->fPos.fX, temp->fPos.fY,
171 temp->fSrcRect.width(),
172 temp->fSrcRect.height());
173 canvas->drawBitmapRectToRect(*temp->fBM, &src, dst, temp->fPaint );
174 canvas->restore();
175
176 if (it.isValid()) {
177 // This save is needed since the BBH will automatically issu e
178 // a restore to balanced the saveLayer we're skipping
179 canvas->save();
180
181 // At this point we know that the PictureStateTree was aimin g
182 // for some draw op within temp's saveLayer (although potent ially
183 // in a separate saveLayer nested inside it).
184 // We need to skip all the operations inside temp's range
185 // along with all the associated state changes but update
186 // the state tree to the first operation outside temp's rang e.
187
188 uint32_t skipTo;
189 do {
190 skipTo = it.nextDraw();
191 if (kDrawComplete == skipTo) {
192 break;
193 }
194
195 if (skipTo <= temp->fStop) {
196 reader.setOffset(skipTo);
197 uint32_t size;
198 DrawType op = ReadOpAndSize(&reader, &size);
199 // Since we are relying on the normal SkPictureState Tree
200 // playback we need to convert any nested saveLayer calls
201 // it may issue into saves (so that all its internal
202 // restores will be balanced).
203 if (SAVE_LAYER == op) {
204 canvas->save();
205 }
206 }
207 } while (skipTo <= temp->fStop);
208
209 if (kDrawComplete == skipTo) {
210 break;
211 }
212
213 reader.setOffset(skipTo);
214 } else {
215 reader.setOffset(temp->fStop);
216 uint32_t size;
217 SkDEBUGCODE(DrawType op = ) ReadOpAndSize(&reader, &size);
218 SkASSERT(RESTORE == op);
219 }
220 continue;
221 }
222 } 275 }
223 276
224 fCurOffset = reader.offset(); 277 fCurOffset = reader.offset();
225 uint32_t size; 278 uint32_t size;
226 DrawType op = ReadOpAndSize(&reader, &size); 279 DrawType op = ReadOpAndSize(&reader, &size);
227 size_t skipTo = 0;
228 if (NOOP == op) { 280 if (NOOP == op) {
229 // NOOPs are to be ignored - do not propagate them any further 281 // NOOPs are to be ignored - do not propagate them any further
230 skipTo = fCurOffset + size; 282 SkipIterTo(&it, &reader, fCurOffset + size);
231 }
232
233 if (0 != skipTo) {
234 if (it.isValid()) {
235 // If using a bounding box hierarchy, advance the state tree
236 // iterator until at or after skipTo
237 uint32_t adjustedSkipTo;
238 do {
239 adjustedSkipTo = it.nextDraw();
240 } while (adjustedSkipTo < skipTo);
241 skipTo = adjustedSkipTo;
242 }
243 if (kDrawComplete == skipTo) {
244 break;
245 }
246 reader.setOffset(skipTo);
247 continue; 283 continue;
248 } 284 }
249 285
250 this->handleOp(&reader, op, size, canvas, initialMatrix); 286 this->handleOp(&reader, op, size, canvas, initialMatrix);
251 287
252 if (it.isValid()) { 288 StepIterator(&it, &reader);
253 uint32_t skipTo = it.nextDraw();
254 if (kDrawComplete == skipTo) {
255 break;
256 }
257 reader.setOffset(skipTo);
258 }
259 } 289 }
260 } 290 }
261 291
262 void SkPicturePlayback::handleOp(SkReader32* reader, 292 void SkPicturePlayback::handleOp(SkReader32* reader,
263 DrawType op, 293 DrawType op,
264 uint32_t size, 294 uint32_t size,
265 SkCanvas* canvas, 295 SkCanvas* canvas,
266 const SkMatrix& initialMatrix) { 296 const SkMatrix& initialMatrix) {
267 switch (op) { 297 switch (op) {
268 case CLIP_PATH: { 298 case CLIP_PATH: {
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 case TRANSLATE: { 596 case TRANSLATE: {
567 SkScalar dx = reader->readScalar(); 597 SkScalar dx = reader->readScalar();
568 SkScalar dy = reader->readScalar(); 598 SkScalar dy = reader->readScalar();
569 canvas->translate(dx, dy); 599 canvas->translate(dx, dy);
570 } break; 600 } break;
571 default: 601 default:
572 SkASSERT(0); 602 SkASSERT(0);
573 } 603 }
574 } 604 }
575 605
OLDNEW
« no previous file with comments | « src/core/SkPicturePlayback.h ('k') | src/core/SkPictureStateTree.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698