OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SkPictureRecord.h" | 8 #include "SkPictureRecord.h" |
9 #include "SkTSearch.h" | 9 #include "SkTSearch.h" |
10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 } | 190 } |
191 | 191 |
192 bool SkPictureRecord::isDrawingToLayer() const { | 192 bool SkPictureRecord::isDrawingToLayer() const { |
193 return fFirstSavedLayerIndex != kNoSavedLayerIndex; | 193 return fFirstSavedLayerIndex != kNoSavedLayerIndex; |
194 } | 194 } |
195 | 195 |
196 /* | 196 /* |
197 * Read the op code from 'offset' in 'writer' and extract the size too. | 197 * Read the op code from 'offset' in 'writer' and extract the size too. |
198 */ | 198 */ |
199 static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* s ize) { | 199 static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* s ize) { |
200 uint32_t* peek = writer->peek32(offset); | 200 uint32_t peek = writer->peek32(offset); |
201 | 201 |
202 uint32_t op; | 202 uint32_t op; |
203 UNPACK_8_24(*peek, op, *size); | 203 UNPACK_8_24(peek, op, *size); |
204 if (MASK_24 == *size) { | 204 if (MASK_24 == *size) { |
205 // size required its own slot right after the op code | 205 // size required its own slot right after the op code |
206 *size = *writer->peek32(offset+kUInt32Size); | 206 *size = writer->peek32(offset+kUInt32Size); |
207 } | 207 } |
208 return (DrawType) op; | 208 return (DrawType) op; |
209 } | 209 } |
210 | 210 |
211 #ifdef TRACK_COLLAPSE_STATS | 211 #ifdef TRACK_COLLAPSE_STATS |
212 static int gCollapseCount, gCollapseCalls; | 212 static int gCollapseCount, gCollapseCalls; |
213 #endif | 213 #endif |
214 | 214 |
215 // Is the supplied paint simply a color? | 215 // Is the supplied paint simply a color? |
216 static bool is_simple(const SkPaint& p) { | 216 static bool is_simple(const SkPaint& p) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 * SAVE_LAYER | 299 * SAVE_LAYER |
300 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_REC T | 300 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_REC T |
301 * RESTORE | 301 * RESTORE |
302 * where the saveLayer's color can be moved into the drawBitmap*'s paint | 302 * where the saveLayer's color can be moved into the drawBitmap*'s paint |
303 */ | 303 */ |
304 static bool remove_save_layer1(SkWriter32* writer, int32_t offset, | 304 static bool remove_save_layer1(SkWriter32* writer, int32_t offset, |
305 SkPaintDictionary* paintDict) { | 305 SkPaintDictionary* paintDict) { |
306 // back up to the save block | 306 // back up to the save block |
307 // TODO: add a stack to track save*/restore offsets rather than searching ba ckwards | 307 // TODO: add a stack to track save*/restore offsets rather than searching ba ckwards |
308 while (offset > 0) { | 308 while (offset > 0) { |
309 offset = *writer->peek32(offset); | 309 offset = writer->peek32(offset); |
310 } | 310 } |
311 | 311 |
312 int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ }; | 312 int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ }; |
313 CommandInfo result[SK_ARRAY_COUNT(pattern)]; | 313 CommandInfo result[SK_ARRAY_COUNT(pattern)]; |
314 | 314 |
315 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { | 315 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { |
316 return false; | 316 return false; |
317 } | 317 } |
318 | 318 |
319 if (kSaveLayerWithBoundsSize == result[0].fSize) { | 319 if (kSaveLayerWithBoundsSize == result[0].fSize) { |
320 // The saveLayer's bound can offset where the dbm is drawn | 320 // The saveLayer's bound can offset where the dbm is drawn |
321 return false; | 321 return false; |
322 } | 322 } |
323 | 323 |
324 | 324 |
325 return merge_savelayer_paint_into_drawbitmp(writer, paintDict, | 325 return merge_savelayer_paint_into_drawbitmp(writer, paintDict, |
326 result[0], result[1]); | 326 result[0], result[1]); |
327 } | 327 } |
328 | 328 |
329 /* | 329 /* |
330 * Convert the command code located at 'offset' to a NOOP. Leave the size | 330 * Convert the command code located at 'offset' to a NOOP. Leave the size |
331 * field alone so the NOOP can be skipped later. | 331 * field alone so the NOOP can be skipped later. |
332 */ | 332 */ |
333 static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) { | 333 static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) { |
334 uint32_t* ptr = writer->peek32(offset); | 334 uint32_t& command = writer->peek32(offset); |
335 *ptr = (*ptr & MASK_24) | (NOOP << 24); | 335 command = (command & MASK_24) | (NOOP << 24); |
reed1
2014/01/31 14:26:08
I like the idea, but I do find this line, and #371
mtklein
2014/01/31 14:34:26
Yeah, we could do that. Most of these are just re
| |
336 } | 336 } |
337 | 337 |
338 /* | 338 /* |
339 * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint. | 339 * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint. |
340 * Return true on success; false otherwise. | 340 * Return true on success; false otherwise. |
341 */ | 341 */ |
342 static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer, | 342 static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer, |
343 SkPaintDictionary* paintDict, | 343 SkPaintDictionary* paintDict, |
344 const CommandInfo& saveLayerInf o, | 344 const CommandInfo& saveLayerInf o, |
345 const CommandInfo& dbmInfo) { | 345 const CommandInfo& dbmInfo) { |
346 SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp); | 346 SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp); |
347 SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp || | 347 SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp || |
348 DRAW_BITMAP_MATRIX == dbmInfo.fActualOp || | 348 DRAW_BITMAP_MATRIX == dbmInfo.fActualOp || |
349 DRAW_BITMAP_NINE == dbmInfo.fActualOp || | 349 DRAW_BITMAP_NINE == dbmInfo.fActualOp || |
350 DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp); | 350 DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp); |
351 | 351 |
352 uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize); | 352 uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize); |
353 uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize); | 353 uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize); |
354 | 354 |
355 // we have a match, now we need to get the paints involved | 355 // we have a match, now we need to get the paints involved |
356 uint32_t dbmPaintId = *writer->peek32(dbmInfo.fOffset+dbmPaintOffset); | 356 uint32_t dbmPaintId = writer->peek32(dbmInfo.fOffset+dbmPaintOffset); |
357 uint32_t saveLayerPaintId = *writer->peek32(saveLayerInfo.fOffset+slPaintOff set); | 357 uint32_t saveLayerPaintId = writer->peek32(saveLayerInfo.fOffset+slPaintOffs et); |
358 | 358 |
359 if (0 == saveLayerPaintId) { | 359 if (0 == saveLayerPaintId) { |
360 // In this case the saveLayer/restore isn't needed at all - just kill th e saveLayer | 360 // In this case the saveLayer/restore isn't needed at all - just kill th e saveLayer |
361 // and signal the caller (by returning true) to not add the RESTORE op | 361 // and signal the caller (by returning true) to not add the RESTORE op |
362 convert_command_to_noop(writer, saveLayerInfo.fOffset); | 362 convert_command_to_noop(writer, saveLayerInfo.fOffset); |
363 return true; | 363 return true; |
364 } | 364 } |
365 | 365 |
366 if (0 == dbmPaintId) { | 366 if (0 == dbmPaintId) { |
367 // In this case just make the DBM* use the saveLayer's paint, kill the s aveLayer | 367 // In this case just make the DBM* use the saveLayer's paint, kill the s aveLayer |
368 // and signal the caller (by returning true) to not add the RESTORE op | 368 // and signal the caller (by returning true) to not add the RESTORE op |
369 convert_command_to_noop(writer, saveLayerInfo.fOffset); | 369 convert_command_to_noop(writer, saveLayerInfo.fOffset); |
370 uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset); | 370 uint32_t& paintId = writer->peek32(dbmInfo.fOffset+dbmPaintOffset); |
mtklein
2014/01/31 14:34:26
Clearer if I just write
write->peek32(dbmInfo.fOf
| |
371 SkASSERT(0 == *ptr); | 371 paintId = saveLayerPaintId; |
372 *ptr = saveLayerPaintId; | |
373 return true; | 372 return true; |
374 } | 373 } |
375 | 374 |
376 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId) ); | 375 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId) ); |
377 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) { | 376 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) { |
378 return false; | 377 return false; |
379 } | 378 } |
380 | 379 |
381 // For this optimization we only fold the saveLayer and drawBitmapRect | 380 // For this optimization we only fold the saveLayer and drawBitmapRect |
382 // together if the saveLayer's draw is simple (i.e., no fancy effects) and | 381 // together if the saveLayer's draw is simple (i.e., no fancy effects) and |
(...skipping 12 matching lines...) Expand all Loading... | |
395 SkColorGetA(saveLayerPaint->getColor())); | 394 SkColorGetA(saveLayerPaint->getColor())); |
396 dbmPaint->setColor(newColor); | 395 dbmPaint->setColor(newColor); |
397 | 396 |
398 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint); | 397 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint); |
399 if (NULL == data) { | 398 if (NULL == data) { |
400 return false; | 399 return false; |
401 } | 400 } |
402 | 401 |
403 // kill the saveLayer and alter the DBMR2R's paint to be the modified one | 402 // kill the saveLayer and alter the DBMR2R's paint to be the modified one |
404 convert_command_to_noop(writer, saveLayerInfo.fOffset); | 403 convert_command_to_noop(writer, saveLayerInfo.fOffset); |
405 uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset); | 404 uint32_t& paintId = writer->peek32(dbmInfo.fOffset+dbmPaintOffset); |
406 SkASSERT(dbmPaintId == *ptr); | 405 paintId = data->index(); |
407 *ptr = data->index(); | |
408 return true; | 406 return true; |
409 } | 407 } |
410 | 408 |
411 /* | 409 /* |
412 * Restore has just been called (but not recorded), look back at the | 410 * Restore has just been called (but not recorded), look back at the |
413 * matching save* and see if we are in the configuration: | 411 * matching save* and see if we are in the configuration: |
414 * SAVE_LAYER (with NULL == bounds) | 412 * SAVE_LAYER (with NULL == bounds) |
415 * SAVE | 413 * SAVE |
416 * CLIP_RECT | 414 * CLIP_RECT |
417 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R ECT | 415 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R ECT |
418 * RESTORE | 416 * RESTORE |
419 * RESTORE | 417 * RESTORE |
420 * where the saveLayer's color can be moved into the drawBitmap*'s paint | 418 * where the saveLayer's color can be moved into the drawBitmap*'s paint |
421 */ | 419 */ |
422 static bool remove_save_layer2(SkWriter32* writer, int32_t offset, | 420 static bool remove_save_layer2(SkWriter32* writer, int32_t offset, |
423 SkPaintDictionary* paintDict) { | 421 SkPaintDictionary* paintDict) { |
424 | 422 |
425 // back up to the save block | 423 // back up to the save block |
426 // TODO: add a stack to track save*/restore offsets rather than searching ba ckwards | 424 // TODO: add a stack to track save*/restore offsets rather than searching ba ckwards |
427 while (offset > 0) { | 425 while (offset > 0) { |
428 offset = *writer->peek32(offset); | 426 offset = writer->peek32(offset); |
429 } | 427 } |
430 | 428 |
431 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ }; | 429 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ }; |
432 CommandInfo result[SK_ARRAY_COUNT(pattern)]; | 430 CommandInfo result[SK_ARRAY_COUNT(pattern)]; |
433 | 431 |
434 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { | 432 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { |
435 return false; | 433 return false; |
436 } | 434 } |
437 | 435 |
438 if (kSaveLayerWithBoundsSize == result[0].fSize) { | 436 if (kSaveLayerWithBoundsSize == result[0].fSize) { |
(...skipping 16 matching lines...) Expand all Loading... | |
455 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset, | 453 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset, |
456 SkPaintDictionary* paintDict) { | 454 SkPaintDictionary* paintDict) { |
457 #ifdef TRACK_COLLAPSE_STATS | 455 #ifdef TRACK_COLLAPSE_STATS |
458 gCollapseCalls += 1; | 456 gCollapseCalls += 1; |
459 #endif | 457 #endif |
460 | 458 |
461 int32_t restoreOffset = (int32_t)writer->bytesWritten(); | 459 int32_t restoreOffset = (int32_t)writer->bytesWritten(); |
462 | 460 |
463 // back up to the save block | 461 // back up to the save block |
464 while (offset > 0) { | 462 while (offset > 0) { |
465 offset = *writer->peek32(offset); | 463 offset = writer->peek32(offset); |
466 } | 464 } |
467 | 465 |
468 // now offset points to a save | 466 // now offset points to a save |
469 offset = -offset; | 467 offset = -offset; |
470 uint32_t opSize; | 468 uint32_t opSize; |
471 DrawType op = peek_op_and_size(writer, offset, &opSize); | 469 DrawType op = peek_op_and_size(writer, offset, &opSize); |
472 if (SAVE_LAYER == op) { | 470 if (SAVE_LAYER == op) { |
473 // not ready to cull these out yet (mrr) | 471 // not ready to cull these out yet (mrr) |
474 return false; | 472 return false; |
475 } | 473 } |
476 SkASSERT(SAVE == op); | 474 SkASSERT(SAVE == op); |
477 SkASSERT(kSaveSize == opSize); | 475 SkASSERT(kSaveSize == opSize); |
478 | 476 |
479 // get the save flag (last 4-bytes of the space allocated for the opSize) | 477 // get the save flag (last 4-bytes of the space allocated for the opSize) |
480 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) *writer->peek32(offset +4); | 478 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->peek32(offset+ 4); |
481 if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) { | 479 if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) { |
482 // This function's optimization is only correct for kMatrixClip style sa ves. | 480 // This function's optimization is only correct for kMatrixClip style sa ves. |
483 // TODO: set checkMatrix & checkClip booleans here and then check for th e | 481 // TODO: set checkMatrix & checkClip booleans here and then check for th e |
484 // offending operations in the following loop. | 482 // offending operations in the following loop. |
485 return false; | 483 return false; |
486 } | 484 } |
487 | 485 |
488 // Walk forward until we get back to either a draw-verb (abort) or we hit | 486 // Walk forward until we get back to either a draw-verb (abort) or we hit |
489 // our restore (success). | 487 // our restore (success). |
490 int32_t saveOffset = offset; | 488 int32_t saveOffset = offset; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
687 return false; | 685 return false; |
688 default: | 686 default: |
689 SkDEBUGFAIL("unknown region op"); | 687 SkDEBUGFAIL("unknown region op"); |
690 return false; | 688 return false; |
691 } | 689 } |
692 } | 690 } |
693 | 691 |
694 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) { | 692 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) { |
695 int32_t offset = fRestoreOffsetStack.top(); | 693 int32_t offset = fRestoreOffsetStack.top(); |
696 while (offset > 0) { | 694 while (offset > 0) { |
697 uint32_t* peek = fWriter.peek32(offset); | 695 uint32_t& peek = fWriter.peek32(offset); |
698 offset = *peek; | 696 offset = peek; |
699 *peek = restoreOffset; | 697 peek = restoreOffset; |
700 } | 698 } |
701 | 699 |
702 #ifdef SK_DEBUG | 700 #ifdef SK_DEBUG |
703 // assert that the final offset value points to a save verb | 701 // assert that the final offset value points to a save verb |
704 uint32_t opSize; | 702 uint32_t opSize; |
705 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); | 703 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); |
706 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); | 704 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); |
707 #endif | 705 #endif |
708 } | 706 } |
709 | 707 |
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1521 void SkPictureRecord::validateRegions() const { | 1519 void SkPictureRecord::validateRegions() const { |
1522 int count = fRegions.count(); | 1520 int count = fRegions.count(); |
1523 SkASSERT((unsigned) count < 0x1000); | 1521 SkASSERT((unsigned) count < 0x1000); |
1524 for (int index = 0; index < count; index++) { | 1522 for (int index = 0; index < count; index++) { |
1525 const SkFlatData* region = fRegions[index]; | 1523 const SkFlatData* region = fRegions[index]; |
1526 SkASSERT(region); | 1524 SkASSERT(region); |
1527 // region->validate(); | 1525 // region->validate(); |
1528 } | 1526 } |
1529 } | 1527 } |
1530 #endif | 1528 #endif |
OLD | NEW |