| 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->read32At(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->read32At(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->read32At(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->read32At(offset); |
| 335 *ptr = (*ptr & MASK_24) | (NOOP << 24); | 335 writer->write32At(offset, (command & MASK_24) | (NOOP << 24)); |
| 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->read32At(dbmInfo.fOffset+dbmPaintOffset); |
| 357 uint32_t saveLayerPaintId = *writer->peek32(saveLayerInfo.fOffset+slPaintOff
set); | 357 uint32_t saveLayerPaintId = writer->read32At(saveLayerInfo.fOffset+slPaintOf
fset); |
| 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 writer->write32At(dbmInfo.fOffset+dbmPaintOffset, saveLayerPaintId); |
| 371 SkASSERT(0 == *ptr); | |
| 372 *ptr = saveLayerPaintId; | |
| 373 return true; | 371 return true; |
| 374 } | 372 } |
| 375 | 373 |
| 376 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId)
); | 374 SkAutoTDelete<SkPaint> saveLayerPaint(paintDict->unflatten(saveLayerPaintId)
); |
| 377 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) { | 375 if (NULL == saveLayerPaint.get() || !is_simple(*saveLayerPaint)) { |
| 378 return false; | 376 return false; |
| 379 } | 377 } |
| 380 | 378 |
| 381 // For this optimization we only fold the saveLayer and drawBitmapRect | 379 // 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 | 380 // 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())); | 393 SkColorGetA(saveLayerPaint->getColor())); |
| 396 dbmPaint->setColor(newColor); | 394 dbmPaint->setColor(newColor); |
| 397 | 395 |
| 398 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint); | 396 const SkFlatData* data = paintDict->findAndReturnFlat(*dbmPaint); |
| 399 if (NULL == data) { | 397 if (NULL == data) { |
| 400 return false; | 398 return false; |
| 401 } | 399 } |
| 402 | 400 |
| 403 // kill the saveLayer and alter the DBMR2R's paint to be the modified one | 401 // kill the saveLayer and alter the DBMR2R's paint to be the modified one |
| 404 convert_command_to_noop(writer, saveLayerInfo.fOffset); | 402 convert_command_to_noop(writer, saveLayerInfo.fOffset); |
| 405 uint32_t* ptr = writer->peek32(dbmInfo.fOffset+dbmPaintOffset); | 403 writer->write32At(dbmInfo.fOffset+dbmPaintOffset, data->index()); |
| 406 SkASSERT(dbmPaintId == *ptr); | |
| 407 *ptr = data->index(); | |
| 408 return true; | 404 return true; |
| 409 } | 405 } |
| 410 | 406 |
| 411 /* | 407 /* |
| 412 * Restore has just been called (but not recorded), look back at the | 408 * Restore has just been called (but not recorded), look back at the |
| 413 * matching save* and see if we are in the configuration: | 409 * matching save* and see if we are in the configuration: |
| 414 * SAVE_LAYER (with NULL == bounds) | 410 * SAVE_LAYER (with NULL == bounds) |
| 415 * SAVE | 411 * SAVE |
| 416 * CLIP_RECT | 412 * CLIP_RECT |
| 417 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R
ECT | 413 * DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R
ECT |
| 418 * RESTORE | 414 * RESTORE |
| 419 * RESTORE | 415 * RESTORE |
| 420 * where the saveLayer's color can be moved into the drawBitmap*'s paint | 416 * where the saveLayer's color can be moved into the drawBitmap*'s paint |
| 421 */ | 417 */ |
| 422 static bool remove_save_layer2(SkWriter32* writer, int32_t offset, | 418 static bool remove_save_layer2(SkWriter32* writer, int32_t offset, |
| 423 SkPaintDictionary* paintDict) { | 419 SkPaintDictionary* paintDict) { |
| 424 | 420 |
| 425 // back up to the save block | 421 // back up to the save block |
| 426 // TODO: add a stack to track save*/restore offsets rather than searching ba
ckwards | 422 // TODO: add a stack to track save*/restore offsets rather than searching ba
ckwards |
| 427 while (offset > 0) { | 423 while (offset > 0) { |
| 428 offset = *writer->peek32(offset); | 424 offset = writer->read32At(offset); |
| 429 } | 425 } |
| 430 | 426 |
| 431 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE,
/* RESTORE */ }; | 427 int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE,
/* RESTORE */ }; |
| 432 CommandInfo result[SK_ARRAY_COUNT(pattern)]; | 428 CommandInfo result[SK_ARRAY_COUNT(pattern)]; |
| 433 | 429 |
| 434 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { | 430 if (!match(writer, -offset, pattern, result, SK_ARRAY_COUNT(pattern))) { |
| 435 return false; | 431 return false; |
| 436 } | 432 } |
| 437 | 433 |
| 438 if (kSaveLayerWithBoundsSize == result[0].fSize) { | 434 if (kSaveLayerWithBoundsSize == result[0].fSize) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 455 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset, | 451 static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset, |
| 456 SkPaintDictionary* paintDict) { | 452 SkPaintDictionary* paintDict) { |
| 457 #ifdef TRACK_COLLAPSE_STATS | 453 #ifdef TRACK_COLLAPSE_STATS |
| 458 gCollapseCalls += 1; | 454 gCollapseCalls += 1; |
| 459 #endif | 455 #endif |
| 460 | 456 |
| 461 int32_t restoreOffset = (int32_t)writer->bytesWritten(); | 457 int32_t restoreOffset = (int32_t)writer->bytesWritten(); |
| 462 | 458 |
| 463 // back up to the save block | 459 // back up to the save block |
| 464 while (offset > 0) { | 460 while (offset > 0) { |
| 465 offset = *writer->peek32(offset); | 461 offset = writer->read32At(offset); |
| 466 } | 462 } |
| 467 | 463 |
| 468 // now offset points to a save | 464 // now offset points to a save |
| 469 offset = -offset; | 465 offset = -offset; |
| 470 uint32_t opSize; | 466 uint32_t opSize; |
| 471 DrawType op = peek_op_and_size(writer, offset, &opSize); | 467 DrawType op = peek_op_and_size(writer, offset, &opSize); |
| 472 if (SAVE_LAYER == op) { | 468 if (SAVE_LAYER == op) { |
| 473 // not ready to cull these out yet (mrr) | 469 // not ready to cull these out yet (mrr) |
| 474 return false; | 470 return false; |
| 475 } | 471 } |
| 476 SkASSERT(SAVE == op); | 472 SkASSERT(SAVE == op); |
| 477 SkASSERT(kSaveSize == opSize); | 473 SkASSERT(kSaveSize == opSize); |
| 478 | 474 |
| 479 // get the save flag (last 4-bytes of the space allocated for the opSize) | 475 // get the save flag (last 4-bytes of the space allocated for the opSize) |
| 480 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) *writer->peek32(offset
+4); | 476 SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->read32At(offse
t+4); |
| 481 if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) { | 477 if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) { |
| 482 // This function's optimization is only correct for kMatrixClip style sa
ves. | 478 // 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 | 479 // TODO: set checkMatrix & checkClip booleans here and then check for th
e |
| 484 // offending operations in the following loop. | 480 // offending operations in the following loop. |
| 485 return false; | 481 return false; |
| 486 } | 482 } |
| 487 | 483 |
| 488 // Walk forward until we get back to either a draw-verb (abort) or we hit | 484 // Walk forward until we get back to either a draw-verb (abort) or we hit |
| 489 // our restore (success). | 485 // our restore (success). |
| 490 int32_t saveOffset = offset; | 486 int32_t saveOffset = offset; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 return false; | 683 return false; |
| 688 default: | 684 default: |
| 689 SkDEBUGFAIL("unknown region op"); | 685 SkDEBUGFAIL("unknown region op"); |
| 690 return false; | 686 return false; |
| 691 } | 687 } |
| 692 } | 688 } |
| 693 | 689 |
| 694 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
restoreOffset) { | 690 void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
restoreOffset) { |
| 695 int32_t offset = fRestoreOffsetStack.top(); | 691 int32_t offset = fRestoreOffsetStack.top(); |
| 696 while (offset > 0) { | 692 while (offset > 0) { |
| 697 uint32_t* peek = fWriter.peek32(offset); | 693 uint32_t peek = fWriter.read32At(offset); |
| 698 offset = *peek; | 694 fWriter.write32At(offset, restoreOffset); |
| 699 *peek = restoreOffset; | 695 offset = peek; |
| 700 } | 696 } |
| 701 | 697 |
| 702 #ifdef SK_DEBUG | 698 #ifdef SK_DEBUG |
| 703 // assert that the final offset value points to a save verb | 699 // assert that the final offset value points to a save verb |
| 704 uint32_t opSize; | 700 uint32_t opSize; |
| 705 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); | 701 DrawType drawOp = peek_op_and_size(&fWriter, -offset, &opSize); |
| 706 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); | 702 SkASSERT(SAVE == drawOp || SAVE_LAYER == drawOp); |
| 707 #endif | 703 #endif |
| 708 } | 704 } |
| 709 | 705 |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1521 void SkPictureRecord::validateRegions() const { | 1517 void SkPictureRecord::validateRegions() const { |
| 1522 int count = fRegions.count(); | 1518 int count = fRegions.count(); |
| 1523 SkASSERT((unsigned) count < 0x1000); | 1519 SkASSERT((unsigned) count < 0x1000); |
| 1524 for (int index = 0; index < count; index++) { | 1520 for (int index = 0; index < count; index++) { |
| 1525 const SkFlatData* region = fRegions[index]; | 1521 const SkFlatData* region = fRegions[index]; |
| 1526 SkASSERT(region); | 1522 SkASSERT(region); |
| 1527 // region->validate(); | 1523 // region->validate(); |
| 1528 } | 1524 } |
| 1529 } | 1525 } |
| 1530 #endif | 1526 #endif |
| OLD | NEW |