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

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

Issue 725143002: More SkPicture cleanup (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: newlines Created 6 years, 1 month 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 | « include/core/SkPicture.h ('k') | src/core/SkPicturePlayback.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 /* 2 /*
3 * Copyright 2007 The Android Open Source Project 3 * Copyright 2007 The Android Open Source Project
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 8
9 9
10 #include "SkPictureFlat.h" 10 #include "SkPictureFlat.h"
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 >= kNumAAConcavePathsTol) 250 >= kNumAAConcavePathsTol)
251 *reason = "Too many anti-aliased concave paths."; 251 *reason = "Too many anti-aliased concave paths.";
252 else 252 else
253 *reason = "Unknown reason for GPU unsuitability."; 253 *reason = "Unknown reason for GPU unsuitability.";
254 } 254 }
255 return ret; 255 return ret;
256 } 256 }
257 257
258 /////////////////////////////////////////////////////////////////////////////// 258 ///////////////////////////////////////////////////////////////////////////////
259 259
260 // fRecord OK
261 SkPicture::SkPicture(SkScalar width, SkScalar height,
262 const SkPictureRecord& record,
263 bool deepCopyOps)
264 : fCullWidth(width)
265 , fCullHeight(height)
266 , fAnalysis() {
267 this->needsNewGenID();
268
269 SkPictInfo info;
270 this->createHeader(&info);
271 fData.reset(SkNEW_ARGS(SkPictureData, (record, info, deepCopyOps)));
272 }
273
274 // Create an SkPictureData-backed SkPicture from an SkRecord.
275 // This for compatibility with serialization code only. This is not cheap.
276 SkPicture* SkPicture::Backport(const SkRecord& src, const SkRect& cullRect) {
277 SkPictureRecord rec(SkISize::Make(cullRect.width(), cullRect.height()), 0/*f lags*/);
278 rec.beginRecording();
279 SkRecordDraw(src, &rec, NULL/*bbh*/, NULL/*callback*/);
280 rec.endRecording();
281 return SkNEW_ARGS(SkPicture, (cullRect.width(), cullRect.height(), rec, fals e/*deepCopyOps*/));
282 }
283
284 // fRecord OK
285 SkPicture::~SkPicture() { 260 SkPicture::~SkPicture() {
286 this->callDeletionListeners(); 261 this->callDeletionListeners();
287 } 262 }
288 263
289 // fRecord OK
290 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t { 264 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) cons t {
291 fAccelData.reset(SkRef(data)); 265 fAccelData.reset(SkRef(data));
292 } 266 }
293 267
294 // fRecord OK
295 const SkPicture::AccelData* SkPicture::EXPERIMENTAL_getAccelData( 268 const SkPicture::AccelData* SkPicture::EXPERIMENTAL_getAccelData(
296 SkPicture::AccelData::Key key) const { 269 SkPicture::AccelData::Key key) const {
297 if (fAccelData.get() && fAccelData->getKey() == key) { 270 if (fAccelData.get() && fAccelData->getKey() == key) {
298 return fAccelData.get(); 271 return fAccelData.get();
299 } 272 }
300 return NULL; 273 return NULL;
301 } 274 }
302 275
303 // fRecord OK
304 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() { 276 SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
305 static int32_t gNextID = 0; 277 static int32_t gNextID = 0;
306 278
307 int32_t id = sk_atomic_inc(&gNextID); 279 int32_t id = sk_atomic_inc(&gNextID);
308 if (id >= 1 << (8 * sizeof(Domain))) { 280 if (id >= 1 << (8 * sizeof(Domain))) {
309 SK_CRASH(); 281 SK_CRASH();
310 } 282 }
311 283
312 return static_cast<Domain>(id); 284 return static_cast<Domain>(id);
313 } 285 }
314 286
315 /////////////////////////////////////////////////////////////////////////////// 287 ///////////////////////////////////////////////////////////////////////////////
316 288
317 // fRecord OK
318 void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) cons t { 289 void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) cons t {
319 SkASSERT(canvas); 290 SkASSERT(canvas);
320 SkASSERT(fData.get() || fRecord.get());
321 291
322 if (fData.get()) { 292 // If the query contains the whole picture, don't bother with the BBH.
323 SkPicturePlayback playback(this); 293 SkRect clipBounds = { 0, 0, 0, 0 };
324 playback.draw(canvas, callback); 294 (void)canvas->getClipBounds(&clipBounds);
325 } 295 const bool useBBH = !clipBounds.contains(this->cullRect());
326 if (fRecord.get()) {
327 // If the query contains the whole picture, don't bother with the BBH.
328 SkRect clipBounds = { 0, 0, 0, 0 };
329 (void)canvas->getClipBounds(&clipBounds);
330 const bool useBBH = !clipBounds.contains(this->cullRect());
331 296
332 SkRecordDraw(*fRecord, canvas, useBBH ? fBBH.get() : NULL, callback); 297 SkRecordDraw(*fRecord, canvas, useBBH ? fBBH.get() : NULL, callback);
333 }
334 } 298 }
335 299
336 /////////////////////////////////////////////////////////////////////////////// 300 ///////////////////////////////////////////////////////////////////////////////
337 301
338 #include "SkStream.h" 302 #include "SkStream.h"
339 303
340 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' }; 304 static const char kMagic[] = { 's', 'k', 'i', 'a', 'p', 'i', 'c', 't' };
341 305
342 // fRecord OK
343 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) { 306 bool SkPicture::IsValidPictInfo(const SkPictInfo& info) {
344 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) { 307 if (0 != memcmp(info.fMagic, kMagic, sizeof(kMagic))) {
345 return false; 308 return false;
346 } 309 }
347 310
348 if (info.fVersion < MIN_PICTURE_VERSION || 311 if (info.fVersion < MIN_PICTURE_VERSION ||
349 info.fVersion > CURRENT_PICTURE_VERSION) { 312 info.fVersion > CURRENT_PICTURE_VERSION) {
350 return false; 313 return false;
351 } 314 }
352 315
353 return true; 316 return true;
354 } 317 }
355 318
356 // fRecord OK
357 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) { 319 bool SkPicture::InternalOnly_StreamIsSKP(SkStream* stream, SkPictInfo* pInfo) {
358 if (NULL == stream) { 320 if (NULL == stream) {
359 return false; 321 return false;
360 } 322 }
361 323
362 // Check magic bytes. 324 // Check magic bytes.
363 SkPictInfo info; 325 SkPictInfo info;
364 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 326 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
365 327
366 if (!stream->read(&info.fMagic, sizeof(kMagic))) { 328 if (!stream->read(&info.fMagic, sizeof(kMagic))) {
(...skipping 23 matching lines...) Expand all
390 if (!IsValidPictInfo(info)) { 352 if (!IsValidPictInfo(info)) {
391 return false; 353 return false;
392 } 354 }
393 355
394 if (pInfo != NULL) { 356 if (pInfo != NULL) {
395 *pInfo = info; 357 *pInfo = info;
396 } 358 }
397 return true; 359 return true;
398 } 360 }
399 361
400 // fRecord OK
401 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo ) { 362 bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer* buffer, SkPictInfo* pInfo ) {
402 // Check magic bytes. 363 // Check magic bytes.
403 SkPictInfo info; 364 SkPictInfo info;
404 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic)); 365 SkASSERT(sizeof(kMagic) == sizeof(info.fMagic));
405 366
406 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) { 367 if (!buffer->readByteArray(&info.fMagic, sizeof(kMagic))) {
407 return false; 368 return false;
408 } 369 }
409 370
410 info.fVersion = buffer->readUInt(); 371 info.fVersion = buffer->readUInt();
(...skipping 16 matching lines...) Expand all
427 if (!IsValidPictInfo(info)) { 388 if (!IsValidPictInfo(info)) {
428 return false; 389 return false;
429 } 390 }
430 391
431 if (pInfo != NULL) { 392 if (pInfo != NULL) {
432 *pInfo = info; 393 *pInfo = info;
433 } 394 }
434 return true; 395 return true;
435 } 396 }
436 397
437 // fRecord OK 398 SkPicture* SkPicture::Forwardport(const SkPictInfo& info, const SkPictureData* d ata) {
438 SkPicture::SkPicture(SkPictureData* data, SkScalar width, SkScalar height) 399 if (!data) {
439 : fData(data) 400 return NULL;
440 , fCullWidth(width) 401 }
441 , fCullHeight(height) 402 SkPicturePlayback playback(data);
442 , fAnalysis() { 403 SkPictureRecorder r;
443 this->needsNewGenID(); 404 playback.draw(r.beginRecording(SkScalarCeilToInt(info.fCullRect.width()),
405 SkScalarCeilToInt(info.fCullRect.height())),
406 NULL/*no callback*/);
407 return r.endRecording();
444 } 408 }
445 409
446 SkPicture* SkPicture::Forwardport(const SkPicture& src) { 410 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
447 SkAutoTDelete<SkRecord> record(SkNEW(SkRecord)); 411 SkPictInfo info;
448 SkRecorder canvas(record.get(), src.cullRect().width(), src.cullRect().heigh t()); 412 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
449 src.playback(&canvas); 413 return NULL;
450 return SkNEW_ARGS(SkPicture, (src.cullRect().width(), src.cullRect().height( ), 414 }
451 record.detach(), NULL/*bbh*/)); 415 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, in fo, proc));
416 return Forwardport(info, data);
452 } 417 }
453 418
454 // fRecord OK 419 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
455 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
456 SkPictInfo info; 420 SkPictInfo info;
457 421 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
458 if (!InternalOnly_StreamIsSKP(stream, &info)) {
459 return NULL; 422 return NULL;
460 } 423 }
461 424 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, in fo));
462 // Check to see if there is a playback to recreate. 425 return Forwardport(info, data);
463 if (stream->readBool()) {
464 SkPictureData* data = SkPictureData::CreateFromStream(stream, info, proc );
465 if (NULL == data) {
466 return NULL;
467 }
468 const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height( ));
469 return Forwardport(src);
470 }
471
472 return NULL;
473 } 426 }
474 427
475 // fRecord OK
476 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
477 SkPictInfo info;
478
479 if (!InternalOnly_BufferIsSKP(&buffer, &info)) {
480 return NULL;
481 }
482
483 // Check to see if there is a playback to recreate.
484 if (buffer.readBool()) {
485 SkPictureData* data = SkPictureData::CreateFromBuffer(buffer, info);
486 if (NULL == data) {
487 return NULL;
488 }
489 const SkPicture src(data, info.fCullRect.width(), info.fCullRect.height( ));
490 return Forwardport(src);
491 }
492
493 return NULL;
494 }
495
496 // fRecord OK
497 void SkPicture::createHeader(SkPictInfo* info) const { 428 void SkPicture::createHeader(SkPictInfo* info) const {
498 // Copy magic bytes at the beginning of the header 429 // Copy magic bytes at the beginning of the header
499 SkASSERT(sizeof(kMagic) == 8); 430 SkASSERT(sizeof(kMagic) == 8);
500 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic)); 431 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
501 memcpy(info->fMagic, kMagic, sizeof(kMagic)); 432 memcpy(info->fMagic, kMagic, sizeof(kMagic));
502 433
503 // Set picture info after magic bytes in the header 434 // Set picture info after magic bytes in the header
504 info->fVersion = CURRENT_PICTURE_VERSION; 435 info->fVersion = CURRENT_PICTURE_VERSION;
505 info->fCullRect = this->cullRect(); 436 info->fCullRect = this->cullRect();
506 info->fFlags = SkPictInfo::kCrossProcess_Flag; 437 info->fFlags = SkPictInfo::kCrossProcess_Flag;
507 // TODO: remove this flag, since we're always float (now) 438 // TODO: remove this flag, since we're always float (now)
508 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag; 439 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
509 440
510 if (8 == sizeof(void*)) { 441 if (8 == sizeof(void*)) {
511 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag; 442 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
512 } 443 }
513 } 444 }
514 445
515 // fRecord OK 446 // This for compatibility with serialization code only. This is not cheap.
447 SkPictureData* SkPicture::Backport(const SkRecord& src, const SkPictInfo& info) {
448 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.hei ght()), 0/*flags*/);
449 rec.beginRecording();
450 SkRecordDraw(src, &rec, NULL/*bbh*/, NULL/*callback*/);
451 rec.endRecording();
452 return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
453 }
454
455
516 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { 456 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
517 const SkPictureData* data = fData.get();
518
519 // If we're a new-format picture, backport to old format for serialization.
520 SkAutoTDelete<SkPicture> oldFormat;
521 if (NULL == data && fRecord.get()) {
522 oldFormat.reset(Backport(*fRecord, this->cullRect()));
523 data = oldFormat->fData.get();
524 SkASSERT(data);
525 }
526
527 SkPictInfo info; 457 SkPictInfo info;
528 this->createHeader(&info); 458 this->createHeader(&info);
529 SkASSERT(sizeof(SkPictInfo) == 32); 459 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info));
460
530 stream->write(&info, sizeof(info)); 461 stream->write(&info, sizeof(info));
531
532 if (data) { 462 if (data) {
533 stream->writeBool(true); 463 stream->writeBool(true);
534 data->serialize(stream, encoder); 464 data->serialize(stream, encoder);
535 } else { 465 } else {
536 stream->writeBool(false); 466 stream->writeBool(false);
537 } 467 }
538 } 468 }
539 469
540 // fRecord OK
541 void SkPicture::flatten(SkWriteBuffer& buffer) const { 470 void SkPicture::flatten(SkWriteBuffer& buffer) const {
542 const SkPictureData* data = fData.get();
543
544 // If we're a new-format picture, backport to old format for serialization.
545 SkAutoTDelete<SkPicture> oldFormat;
546 if (NULL == data && fRecord.get()) {
547 oldFormat.reset(Backport(*fRecord, this->cullRect()));
548 data = oldFormat->fData.get();
549 SkASSERT(data);
550 }
551
552 SkPictInfo info; 471 SkPictInfo info;
553 this->createHeader(&info); 472 this->createHeader(&info);
473 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info));
474
554 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); 475 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
555 buffer.writeUInt(info.fVersion); 476 buffer.writeUInt(info.fVersion);
556 buffer.writeRect(info.fCullRect); 477 buffer.writeRect(info.fCullRect);
557 buffer.writeUInt(info.fFlags); 478 buffer.writeUInt(info.fFlags);
558
559 if (data) { 479 if (data) {
560 buffer.writeBool(true); 480 buffer.writeBool(true);
561 data->flatten(buffer); 481 data->flatten(buffer);
562 } else { 482 } else {
563 buffer.writeBool(false); 483 buffer.writeBool(false);
564 } 484 }
565 } 485 }
566 486
567 #if SK_SUPPORT_GPU 487 #if SK_SUPPORT_GPU
568 // fRecord OK 488 bool SkPicture::suitableForGpuRasterization(GrContext*, const char **reason) con st {
569 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const { 489 return fAnalysis.suitableForGpuRasterization(reason, 0);
570 if (fRecord.get()) {
571 return fAnalysis.suitableForGpuRasterization(reason, 0);
572 }
573 if (NULL == fData.get()) {
574 if (reason) {
575 *reason = "Missing internal data.";
576 }
577 return false;
578 }
579
580 return fData->suitableForGpuRasterization(context, reason);
581 } 490 }
582 #endif 491 #endif
583 492
584 // fRecord OK 493 bool SkPicture::hasText() const { return fAnalysis.fHasText; }
585 bool SkPicture::hasText() const { 494 bool SkPicture::willPlayBackBitmaps() const { return fAnalysis.fWillPlaybackBitm aps; }
586 if (fRecord.get()) { 495 int SkPicture::approximateOpCount() const { return fRecord->count(); }
587 return fAnalysis.fHasText;
588 }
589 if (fData.get()) {
590 return fData->hasText();
591 }
592 SkFAIL("Unreachable");
593 return false;
594 }
595 496
596 // fRecord OK 497 static int32_t gPictureGenerationID = SK_InvalidGenID; // This will be set at l ink time.
597 bool SkPicture::willPlayBackBitmaps() const {
598 if (fRecord.get()) {
599 return fAnalysis.fWillPlaybackBitmaps;
600 }
601 if (fData.get()) {
602 return fData->containsBitmaps();
603 }
604 SkFAIL("Unreachable");
605 return false;
606 }
607 498
608 // fRecord OK
609 static int32_t next_picture_generation_id() { 499 static int32_t next_picture_generation_id() {
610 static int32_t gPictureGenerationID = 0; 500 // Loop in case our global wraps around.
611 // do a loop in case our global wraps around, as we never want to
612 // return a 0
613 int32_t genID; 501 int32_t genID;
614 do { 502 do {
615 genID = sk_atomic_inc(&gPictureGenerationID) + 1; 503 genID = sk_atomic_inc(&gPictureGenerationID) + 1;
616 } while (SK_InvalidGenID == genID); 504 } while (SK_InvalidGenID == genID);
617 return genID; 505 return genID;
618 } 506 }
619 507
620 // fRecord OK
621 uint32_t SkPicture::uniqueID() const { 508 uint32_t SkPicture::uniqueID() const {
622 if (SK_InvalidGenID == fUniqueID) { 509 if (SK_InvalidGenID == fUniqueID) {
623 fUniqueID = next_picture_generation_id(); 510 fUniqueID = next_picture_generation_id();
624 } 511 }
625 return fUniqueID; 512 return fUniqueID;
626 } 513 }
627 514
628 // fRecord OK
629 SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHi erarchy* bbh) 515 SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHi erarchy* bbh)
630 : fCullWidth(width) 516 : fCullWidth(width)
631 , fCullHeight(height) 517 , fCullHeight(height)
632 , fRecord(record) 518 , fRecord(record)
633 , fBBH(SkSafeRef(bbh)) 519 , fBBH(SkSafeRef(bbh))
634 , fAnalysis(*fRecord) { 520 , fAnalysis(*fRecord) {
635 this->needsNewGenID(); 521 this->needsNewGenID();
636 } 522 }
637 523
638 // Note that we are assuming that this entry point will only be called from 524 // Note that we are assuming that this entry point will only be called from
639 // one thread. Currently the only client of this method is 525 // one thread. Currently the only client of this method is
640 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single 526 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
641 // thread. 527 // thread.
642 void SkPicture::addDeletionListener(DeletionListener* listener) const { 528 void SkPicture::addDeletionListener(DeletionListener* listener) const {
643 SkASSERT(listener); 529 SkASSERT(listener);
644 530
645 *fDeletionListeners.append() = SkRef(listener); 531 *fDeletionListeners.append() = SkRef(listener);
646 } 532 }
647 533
648 void SkPicture::callDeletionListeners() { 534 void SkPicture::callDeletionListeners() {
649 for (int i = 0; i < fDeletionListeners.count(); ++i) { 535 for (int i = 0; i < fDeletionListeners.count(); ++i) {
650 fDeletionListeners[i]->onDeletion(this->uniqueID()); 536 fDeletionListeners[i]->onDeletion(this->uniqueID());
651 } 537 }
652 538
653 fDeletionListeners.unrefAll(); 539 fDeletionListeners.unrefAll();
654 } 540 }
655
656 // fRecord OK
657 int SkPicture::approximateOpCount() const {
658 SkASSERT(fRecord.get() || fData.get());
659 if (fRecord.get()) {
660 return fRecord->count();
661 }
662 if (fData.get()) {
663 return fData->opCount();
664 }
665 return 0;
666 }
OLDNEW
« no previous file with comments | « include/core/SkPicture.h ('k') | src/core/SkPicturePlayback.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698