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

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: working 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) {
robertphillips 2014/11/17 14:11:45 newline after '{' and ';' ?
mtklein 2014/11/17 14:21:44 Done.
438 SkPicture::SkPicture(SkPictureData* data, SkScalar width, SkScalar height) 399 if (!data) { return NULL; }
439 : fData(data) 400 SkPicturePlayback playback(data);
440 , fCullWidth(width) 401 SkPictureRecorder r;
441 , fCullHeight(height) 402 playback.draw(r.beginRecording(SkScalarCeilToInt(info.fCullRect.width()),
442 , fAnalysis() { 403 SkScalarCeilToInt(info.fCullRect.height())),
443 this->needsNewGenID(); 404 NULL/*no callback*/);
405 return r.endRecording();
444 } 406 }
445 407
446 SkPicture* SkPicture::Forwardport(const SkPicture& src) { 408 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
447 SkAutoTDelete<SkRecord> record(SkNEW(SkRecord)); 409 SkPictInfo info;
448 SkRecorder canvas(record.get(), src.cullRect().width(), src.cullRect().heigh t()); 410 if (!InternalOnly_StreamIsSKP(stream, &info) || !stream->readBool()) {
449 src.playback(&canvas); 411 return NULL;
450 return SkNEW_ARGS(SkPicture, (src.cullRect().width(), src.cullRect().height( ), 412 }
451 record.detach(), NULL/*bbh*/)); 413 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromStream(stream, in fo, proc));
414 return Forwardport(info, data);
452 } 415 }
453 416
454 // fRecord OK 417 SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
455 SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro c) {
456 SkPictInfo info; 418 SkPictInfo info;
457 419 if (!InternalOnly_BufferIsSKP(&buffer, &info) || !buffer.readBool()) {
458 if (!InternalOnly_StreamIsSKP(stream, &info)) {
459 return NULL; 420 return NULL;
460 } 421 }
461 422 SkAutoTDelete<SkPictureData> data(SkPictureData::CreateFromBuffer(buffer, in fo));
462 // Check to see if there is a playback to recreate. 423 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 } 424 }
474 425
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 { 426 void SkPicture::createHeader(SkPictInfo* info) const {
498 // Copy magic bytes at the beginning of the header 427 // Copy magic bytes at the beginning of the header
499 SkASSERT(sizeof(kMagic) == 8); 428 SkASSERT(sizeof(kMagic) == 8);
500 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic)); 429 SkASSERT(sizeof(kMagic) == sizeof(info->fMagic));
501 memcpy(info->fMagic, kMagic, sizeof(kMagic)); 430 memcpy(info->fMagic, kMagic, sizeof(kMagic));
502 431
503 // Set picture info after magic bytes in the header 432 // Set picture info after magic bytes in the header
504 info->fVersion = CURRENT_PICTURE_VERSION; 433 info->fVersion = CURRENT_PICTURE_VERSION;
505 info->fCullRect = this->cullRect(); 434 info->fCullRect = this->cullRect();
506 info->fFlags = SkPictInfo::kCrossProcess_Flag; 435 info->fFlags = SkPictInfo::kCrossProcess_Flag;
507 // TODO: remove this flag, since we're always float (now) 436 // TODO: remove this flag, since we're always float (now)
508 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag; 437 info->fFlags |= SkPictInfo::kScalarIsFloat_Flag;
509 438
510 if (8 == sizeof(void*)) { 439 if (8 == sizeof(void*)) {
511 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag; 440 info->fFlags |= SkPictInfo::kPtrIs64Bit_Flag;
512 } 441 }
513 } 442 }
514 443
515 // fRecord OK 444 // This for compatibility with serialization code only. This is not cheap.
445 SkPictureData* SkPicture::Backport(const SkRecord& src, const SkPictInfo& info) {
446 SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.hei ght()), 0/*flags*/);
447 rec.beginRecording();
448 SkRecordDraw(src, &rec, NULL/*bbh*/, NULL/*callback*/);
449 rec.endRecording();
450 return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
451 }
452
453
516 void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const { 454 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; 455 SkPictInfo info;
528 this->createHeader(&info); 456 this->createHeader(&info);
529 SkASSERT(sizeof(SkPictInfo) == 32); 457 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info));
458
530 stream->write(&info, sizeof(info)); 459 stream->write(&info, sizeof(info));
531
532 if (data) { 460 if (data) {
533 stream->writeBool(true); 461 stream->writeBool(true);
534 data->serialize(stream, encoder); 462 data->serialize(stream, encoder);
535 } else { 463 } else {
536 stream->writeBool(false); 464 stream->writeBool(false);
537 } 465 }
538 } 466 }
539 467
540 // fRecord OK
541 void SkPicture::flatten(SkWriteBuffer& buffer) const { 468 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; 469 SkPictInfo info;
553 this->createHeader(&info); 470 this->createHeader(&info);
471 SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info));
472
554 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic)); 473 buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
555 buffer.writeUInt(info.fVersion); 474 buffer.writeUInt(info.fVersion);
556 buffer.writeRect(info.fCullRect); 475 buffer.writeRect(info.fCullRect);
557 buffer.writeUInt(info.fFlags); 476 buffer.writeUInt(info.fFlags);
558
559 if (data) { 477 if (data) {
560 buffer.writeBool(true); 478 buffer.writeBool(true);
561 data->flatten(buffer); 479 data->flatten(buffer);
562 } else { 480 } else {
563 buffer.writeBool(false); 481 buffer.writeBool(false);
564 } 482 }
565 } 483 }
566 484
567 #if SK_SUPPORT_GPU 485 #if SK_SUPPORT_GPU
568 // fRecord OK 486 bool SkPicture::suitableForGpuRasterization(GrContext*, const char **reason) con st {
569 bool SkPicture::suitableForGpuRasterization(GrContext* context, const char **rea son) const { 487 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 } 488 }
582 #endif 489 #endif
583 490
584 // fRecord OK 491 bool SkPicture::hasText() const { return fAnalysis.fHasText; }
585 bool SkPicture::hasText() const { 492 bool SkPicture::willPlayBackBitmaps() const { return fAnalysis.fWillPlaybackBitm aps; }
586 if (fRecord.get()) { 493 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 494
596 // fRecord OK 495 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 496
608 // fRecord OK
609 static int32_t next_picture_generation_id() { 497 static int32_t next_picture_generation_id() {
610 static int32_t gPictureGenerationID = 0; 498 // 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; 499 int32_t genID;
614 do { 500 do {
615 genID = sk_atomic_inc(&gPictureGenerationID) + 1; 501 genID = sk_atomic_inc(&gPictureGenerationID) + 1;
616 } while (SK_InvalidGenID == genID); 502 } while (SK_InvalidGenID == genID);
617 return genID; 503 return genID;
618 } 504 }
619 505
620 // fRecord OK
621 uint32_t SkPicture::uniqueID() const { 506 uint32_t SkPicture::uniqueID() const {
622 if (SK_InvalidGenID == fUniqueID) { 507 if (SK_InvalidGenID == fUniqueID) {
623 fUniqueID = next_picture_generation_id(); 508 fUniqueID = next_picture_generation_id();
624 } 509 }
625 return fUniqueID; 510 return fUniqueID;
626 } 511 }
627 512
628 // fRecord OK
629 SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHi erarchy* bbh) 513 SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHi erarchy* bbh)
630 : fCullWidth(width) 514 : fCullWidth(width)
631 , fCullHeight(height) 515 , fCullHeight(height)
632 , fRecord(record) 516 , fRecord(record)
633 , fBBH(SkSafeRef(bbh)) 517 , fBBH(SkSafeRef(bbh))
634 , fAnalysis(*fRecord) { 518 , fAnalysis(*fRecord) {
635 this->needsNewGenID(); 519 this->needsNewGenID();
636 } 520 }
637 521
638 // Note that we are assuming that this entry point will only be called from 522 // 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 523 // one thread. Currently the only client of this method is
640 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single 524 // SkGpuDevice::EXPERIMENTAL_optimize which should be only called from a single
641 // thread. 525 // thread.
642 void SkPicture::addDeletionListener(DeletionListener* listener) const { 526 void SkPicture::addDeletionListener(DeletionListener* listener) const {
643 SkASSERT(listener); 527 SkASSERT(listener);
644 528
645 *fDeletionListeners.append() = SkRef(listener); 529 *fDeletionListeners.append() = SkRef(listener);
646 } 530 }
647 531
648 void SkPicture::callDeletionListeners() { 532 void SkPicture::callDeletionListeners() {
649 for (int i = 0; i < fDeletionListeners.count(); ++i) { 533 for (int i = 0; i < fDeletionListeners.count(); ++i) {
650 fDeletionListeners[i]->onDeletion(this->uniqueID()); 534 fDeletionListeners[i]->onDeletion(this->uniqueID());
651 } 535 }
652 536
653 fDeletionListeners.unrefAll(); 537 fDeletionListeners.unrefAll();
654 } 538 }
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