| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkPictureRecord.h" | 8 #include "SkPictureRecord.h" |
| 9 #include "SkTSearch.h" | 9 #include "SkTSearch.h" |
| 10 #include "SkPixelRef.h" | 10 #include "SkPixelRef.h" |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 198 } |
| 199 | 199 |
| 200 bool SkPictureRecord::isDrawingToLayer() const { | 200 bool SkPictureRecord::isDrawingToLayer() const { |
| 201 return fFirstSavedLayerIndex != kNoSavedLayerIndex; | 201 return fFirstSavedLayerIndex != kNoSavedLayerIndex; |
| 202 } | 202 } |
| 203 | 203 |
| 204 /* | 204 /* |
| 205 * Read the op code from 'offset' in 'writer' and extract the size too. | 205 * Read the op code from 'offset' in 'writer' and extract the size too. |
| 206 */ | 206 */ |
| 207 static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* s
ize) { | 207 static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* s
ize) { |
| 208 uint32_t peek = writer->read32At(offset); | 208 uint32_t peek = writer->readTAt<uint32_t>(offset); |
| 209 | 209 |
| 210 uint32_t op; | 210 uint32_t op; |
| 211 UNPACK_8_24(peek, op, *size); | 211 UNPACK_8_24(peek, op, *size); |
| 212 if (MASK_24 == *size) { | 212 if (MASK_24 == *size) { |
| 213 // size required its own slot right after the op code | 213 // size required its own slot right after the op code |
| 214 *size = writer->read32At(offset+kUInt32Size); | 214 *size = writer->readTAt<uint32_t>(offset + kUInt32Size); |
| 215 } | 215 } |
| 216 return (DrawType) op; | 216 return (DrawType) op; |
| 217 } | 217 } |
| 218 | 218 |
| 219 #ifdef TRACK_COLLAPSE_STATS | 219 #ifdef TRACK_COLLAPSE_STATS |
| 220 static int gCollapseCount, gCollapseCalls; | 220 static int gCollapseCount, gCollapseCalls; |
| 221 #endif | 221 #endif |
| 222 | 222 |
| 223 // Is the supplied paint simply a color? | 223 // Is the supplied paint simply a color? |
| 224 static bool is_simple(const SkPaint& p) { | 224 static bool is_simple(const SkPaint& p) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 * SAVE_LAYER | 307 * SAVE_LAYER |
| 308 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_REC
T | 308 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_REC
T |
| 309 * RESTORE | 309 * RESTORE |
| 310 * where the saveLayer's color can be moved into the drawBitmap*'s paint | 310 * where the saveLayer's color can be moved into the drawBitmap*'s paint |
| 311 */ | 311 */ |
| 312 static bool remove_save_layer1(SkWriter32* writer, int32_t offset, | 312 static bool remove_save_layer1(SkWriter32* writer, int32_t offset, |
| 313 SkPaintDictionary* paintDict) { | 313 SkPaintDictionary* paintDict) { |
| 314 // back up to the save block | 314 // back up to the save block |
| 315 // TODO: add a stack to track save*/restore offsets rather than searching ba
ckwards | 315 // TODO: add a stack to track save*/restore offsets rather than searching ba
ckwards |
| 316 while (offset > 0) { | 316 while (offset > 0) { |
| 317 offset = writer->read32At(offset); | 317 offset = writer->readTAt<uint32_t>(offset); |
| 318 } | 318 } |
| 319 | 319 |
| 320 int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ }; | 320 int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ }; |
| 321 CommandInfo result[SK_ARRAY_COUNT(pattern)]; | 321 CommandInfo result[SK_ARRAY_COUNT(pattern)]; |
| 322 | 322 |
| 323 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { | 323 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { |
| 324 return false; | 324 return false; |
| 325 } | 325 } |
| 326 | 326 |
| 327 if (kSaveLayerWithBoundsSize == result[0].fSize) { | 327 if (kSaveLayerWithBoundsSize == result[0].fSize) { |
| 328 // The saveLayer's bound can offset where the dbm is drawn | 328 // The saveLayer's bound can offset where the dbm is drawn |
| 329 return false; | 329 return false; |
| 330 } | 330 } |
| 331 | 331 |
| 332 return merge_savelayer_paint_into_drawbitmp(writer, paintDict, | 332 return merge_savelayer_paint_into_drawbitmp(writer, paintDict, |
| 333 result[0], result[1]); | 333 result[0], result[1]); |
| 334 } | 334 } |
| 335 | 335 |
| 336 /* | 336 /* |
| 337 * Convert the command code located at 'offset' to a NOOP. Leave the size | 337 * Convert the command code located at 'offset' to a NOOP. Leave the size |
| 338 * field alone so the NOOP can be skipped later. | 338 * field alone so the NOOP can be skipped later. |
| 339 */ | 339 */ |
| 340 static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) { | 340 static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) { |
| 341 uint32_t command = writer->read32At(offset); | 341 uint32_t command = writer->readTAt<uint32_t>(offset); |
| 342 writer->write32At(offset, (command & MASK_24) | (NOOP << 24)); | 342 writer->overwriteTAt(offset, (command & MASK_24) | (NOOP << 24)); |
| 343 } | 343 } |
| 344 | 344 |
| 345 /* | 345 /* |
| 346 * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint. | 346 * Attempt to merge the saveLayer's paint into the drawBitmap*'s paint. |
| 347 * Return true on success; false otherwise. | 347 * Return true on success; false otherwise. |
| 348 */ | 348 */ |
| 349 static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer, | 349 static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer, |
| 350 SkPaintDictionary* paintDict, | 350 SkPaintDictionary* paintDict, |
| 351 const CommandInfo& saveLayerInf
o, | 351 const CommandInfo& saveLayerInf
o, |
| 352 const CommandInfo& dbmInfo) { | 352 const CommandInfo& dbmInfo) { |
| 353 SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp); | 353 SkASSERT(SAVE_LAYER == saveLayerInfo.fActualOp); |
| 354 SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp || | 354 SkASSERT(DRAW_BITMAP == dbmInfo.fActualOp || |
| 355 DRAW_BITMAP_MATRIX == dbmInfo.fActualOp || | 355 DRAW_BITMAP_MATRIX == dbmInfo.fActualOp || |
| 356 DRAW_BITMAP_NINE == dbmInfo.fActualOp || | 356 DRAW_BITMAP_NINE == dbmInfo.fActualOp || |
| 357 DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp); | 357 DRAW_BITMAP_RECT_TO_RECT == dbmInfo.fActualOp); |
| 358 | 358 |
| 359 uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize); | 359 uint32_t dbmPaintOffset = getPaintOffset(dbmInfo.fActualOp, dbmInfo.fSize); |
| 360 uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize); | 360 uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize); |
| 361 | 361 |
| 362 // we have a match, now we need to get the paints involved | 362 // we have a match, now we need to get the paints involved |
| 363 uint32_t dbmPaintId = writer->read32At(dbmInfo.fOffset+dbmPaintOffset); | 363 uint32_t dbmPaintId = writer->readTAt<uint32_t>(dbmInfo.fOffset + dbmPaintOf
fset); |
| 364 uint32_t saveLayerPaintId = writer->read32At(saveLayerInfo.fOffset+slPaintOf
fset); | 364 uint32_t saveLayerPaintId = writer->readTAt<uint32_t>(saveLayerInfo.fOffset
+ slPaintOffset); |
| 365 | 365 |
| 366 if (0 == saveLayerPaintId) { | 366 if (0 == saveLayerPaintId) { |
| 367 // In this case the saveLayer/restore isn't needed at all - just kill th
e saveLayer | 367 // In this case the saveLayer/restore isn't needed at all - just kill th
e saveLayer |
| 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 return true; | 370 return true; |
| 371 } | 371 } |
| 372 | 372 |
| 373 if (0 == dbmPaintId) { | 373 if (0 == dbmPaintId) { |
| 374 // In this case just make the DBM* use the saveLayer's paint, kill the s
aveLayer | 374 // In this case just make the DBM* use the saveLayer's paint, kill the s
aveLayer |
| 375 // and signal the caller (by returning true) to not add the RESTORE op | 375 // and signal the caller (by returning true) to not add the RESTORE op |
| 376 convert_command_to_noop(writer, saveLayerInfo.fOffset); | 376 convert_command_to_noop(writer, saveLayerInfo.fOffset); |
| 377 writer->write32At(dbmInfo.fOffset+dbmPaintOffset, saveLayerPaintId); | 377 writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, saveLayerPaintId)
; |
| 378 return true; | 378 return true; |
| 379 } | 379 } |
| 380 | 380 |
| 381 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId)
); | 381 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId)
); |
| 382 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) { | 382 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) { |
| 383 return false; | 383 return false; |
| 384 } | 384 } |
| 385 | 385 |
| 386 // For this optimization we only fold the saveLayer and drawBitmapRect | 386 // For this optimization we only fold the saveLayer and drawBitmapRect |
| 387 // together if the saveLayer's draw is simple (i.e., no fancy effects) and | 387 // together if the saveLayer's draw is simple (i.e., no fancy effects) and |
| (...skipping 12 matching lines...) Expand all Loading... |
| 400 SkColorGetA(saveLayerPaint->getColor())); | 400 SkColorGetA(saveLayerPaint->getColor())); |
| 401 dbmPaint->setColor(newColor); | 401 dbmPaint->setColor(newColor); |
| 402 | 402 |
| 403 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint); | 403 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint); |
| 404 if (NULL == data) { | 404 if (NULL == data) { |
| 405 return false; | 405 return false; |
| 406 } | 406 } |
| 407 | 407 |
| 408 // kill the saveLayer and alter the DBMR2R's paint to be the modified one | 408 // kill the saveLayer and alter the DBMR2R's paint to be the modified one |
| 409 convert_command_to_noop(writer, saveLayerInfo.fOffset); | 409 convert_command_to_noop(writer, saveLayerInfo.fOffset); |
| 410 writer->write32At(dbmInfo.fOffset+dbmPaintOffset, data->index()); | 410 writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, data->index()); |
| 411 return true; | 411 return true; |
| 412 } | 412 } |
| 413 | 413 |
| 414 /* | 414 /* |
| 415 * Restore has just been called (but not recorded), look back at the | 415 * Restore has just been called (but not recorded), look back at the |
| 416 * matching save* and see if we are in the configuration: | 416 * matching save* and see if we are in the configuration: |
| 417 * SAVE_LAYER (with NULL == bounds) | 417 * SAVE_LAYER (with NULL == bounds) |
| 418 * SAVE | 418 * SAVE |
| 419 * CLIP_RECT | 419 * CLIP_RECT |
| 420 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R
ECT | 420 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R
ECT |
| 421 * RESTORE | 421 * RESTORE |
| 422 * RESTORE | 422 * RESTORE |
| 423 * where the saveLayer's color can be moved into the drawBitmap*'s paint | 423 * where the saveLayer's color can be moved into the drawBitmap*'s paint |
| 424 */ | 424 */ |
| 425 static bool remove_save_layer2(SkWriter32* writer, int32_t offset, | 425 static bool remove_save_layer2(SkWriter32* writer, int32_t offset, |
| 426 SkPaintDictionary* paintDict) { | 426 SkPaintDictionary* paintDict) { |
| 427 | 427 |
| 428 // back up to the save block | 428 // back up to the save block |
| 429 // TODO: add a stack to track save*/restore offsets rather than searching ba
ckwards | 429 // TODO: add a stack to track save*/restore offsets rather than searching ba
ckwards |
| 430 while (offset > 0) { | 430 while (offset > 0) { |
| 431 offset = writer->read32At(offset); | 431 offset = writer->readTAt<uint32_t>(offset); |
| 432 } | 432 } |
| 433 | 433 |
| 434 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE,
/* RESTORE */ }; | 434 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE,
/* RESTORE */ }; |
| 435 CommandInfo result[SK_ARRAY_COUNT(pattern)]; | 435 CommandInfo result[SK_ARRAY_COUNT(pattern)]; |
| 436 | 436 |
| 437 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { | 437 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { |
| 438 return false; | 438 return false; |
| 439 } | 439 } |
| 440 | 440 |
| 441 if (kSaveLayerWithBoundsSize == result[0].fSize) { | 441 if (kSaveLayerWithBoundsSize == result[0].fSize) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 458 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset, | 458 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset, |
| 459 SkPaintDictionary* paintDict) { | 459 SkPaintDictionary* paintDict) { |
| 460 #ifdef TRACK_COLLAPSE_STATS | 460 #ifdef TRACK_COLLAPSE_STATS |
| 461 gCollapseCalls += 1; | 461 gCollapseCalls += 1; |
| 462 #endif | 462 #endif |
| 463 | 463 |
| 464 int32_t restoreOffset = (int32_t)writer->bytesWritten(); | 464 int32_t restoreOffset = (int32_t)writer->bytesWritten(); |
| 465 | 465 |
| 466 // back up to the save block | 466 // back up to the save block |
| 467 while (offset > 0) { | 467 while (offset > 0) { |
| 468 offset = writer->read32At(offset); | 468 offset = writer->readTAt<uint32_t>(offset); |
| 469 } | 469 } |
| 470 | 470 |
| 471 // now offset points to a save | 471 // now offset points to a save |
| 472 offset = -offset; | 472 offset = -offset; |
| 473 uint32_t opSize; | 473 uint32_t opSize; |
| 474 DrawType op = peek_op_and_size(writer, offset, &opSize); | 474 DrawType op = peek_op_and_size(writer, offset, &opSize); |
| 475 if (SAVE_LAYER == op) { | 475 if (SAVE_LAYER == op) { |
| 476 // not ready to cull these out yet (mrr) | 476 // not ready to cull these out yet (mrr) |
| 477 return false; | 477 return false; |
| 478 } | 478 } |
| 479 SkASSERT(SAVE == op); | 479 SkASSERT(SAVE == op); |
| 480 SkASSERT(kSaveSize == opSize); | 480 SkASSERT(kSaveSize == opSize); |
| 481 | 481 |
| 482 // get the save flag (last 4-bytes of the space allocated for the opSize) | 482 // get the save flag (last 4-bytes of the space allocated for the opSize) |
| 483 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->read32At(offse
t+4); | 483 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->readTAt<uint32
_t>(offset + 4); |
| 484 if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) { | 484 if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) { |
| 485 // This function's optimization is only correct for kMatrixClip style sa
ves. | 485 // This function's optimization is only correct for kMatrixClip style sa
ves. |
| 486 // TODO: set checkMatrix & checkClip booleans here and then check for th
e | 486 // TODO: set checkMatrix & checkClip booleans here and then check for th
e |
| 487 // offending operations in the following loop. | 487 // offending operations in the following loop. |
| 488 return false; | 488 return false; |
| 489 } | 489 } |
| 490 | 490 |
| 491 // Walk forward until we get back to either a draw-verb (abort) or we hit | 491 // Walk forward until we get back to either a draw-verb (abort) or we hit |
| 492 // our restore (success). | 492 // our restore (success). |
| 493 int32_t saveOffset = offset; | 493 int32_t saveOffset = offset; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 return false; | 696 return false; |
| 697 default: | 697 default: |
| 698 SkDEBUGFAIL("unknown region op"); | 698 SkDEBUGFAIL("unknown region op"); |
| 699 return false; | 699 return false; |
| 700 } | 700 } |
| 701 } | 701 } |
| 702 | 702 |
| 703 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
restoreOffset) { | 703 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
restoreOffset) { |
| 704 int32_t offset = fRestoreOffsetStack.top(); | 704 int32_t offset = fRestoreOffsetStack.top(); |
| 705 while (offset > 0) { | 705 while (offset > 0) { |
| 706 uint32_t peek = fWriter.read32At(offset); | 706 uint32_t peek = fWriter.readTAt<uint32_t>(offset); |
| 707 fWriter.write32At(offset, restoreOffset); | 707 fWriter.overwriteTAt(offset, restoreOffset); |
| 708 offset = peek; | 708 offset = peek; |
| 709 } | 709 } |
| 710 | 710 |
| 711 #ifdef SK_DEBUG | 711 #ifdef SK_DEBUG |
| 712 // assert that the final offset value points to a save verb | 712 // assert that the final offset value points to a save verb |
| 713 uint32_t opSize; | 713 uint32_t opSize; |
| 714 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); | 714 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); |
| 715 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); | 715 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); |
| 716 #endif | 716 #endif |
| 717 } | 717 } |
| (...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1579 void SkPictureRecord::validateRegions() const { | 1579 void SkPictureRecord::validateRegions() const { |
| 1580 int count = fRegions.count(); | 1580 int count = fRegions.count(); |
| 1581 SkASSERT((unsigned) count < 0x1000); | 1581 SkASSERT((unsigned) count < 0x1000); |
| 1582 for (int index = 0; index < count; index++) { | 1582 for (int index = 0; index < count; index++) { |
| 1583 const SkFlatData* region = fRegions[index]; | 1583 const SkFlatData* region = fRegions[index]; |
| 1584 SkASSERT(region); | 1584 SkASSERT(region); |
| 1585 // region->validate(); | 1585 // region->validate(); |
| 1586 } | 1586 } |
| 1587 } | 1587 } |
| 1588 #endif | 1588 #endif |
| OLD | NEW |