OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. |
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 DidDraw(); | 288 DidDraw(); |
289 } | 289 } |
290 | 290 |
291 SetNeedsCompositingUpdate(); | 291 SetNeedsCompositingUpdate(); |
292 | 292 |
293 return context_.Get(); | 293 return context_.Get(); |
294 } | 294 } |
295 | 295 |
296 bool HTMLCanvasElement::ShouldBeDirectComposited() const { | 296 bool HTMLCanvasElement::ShouldBeDirectComposited() const { |
297 return (context_ && context_->IsComposited()) || | 297 return (context_ && context_->IsComposited()) || |
298 (HasImageBuffer() && Buffer()->IsExpensiveToPaint()) || | 298 (GetImageBuffer() && GetImageBuffer()->IsExpensiveToPaint()) || |
299 (!!surface_layer_bridge_); | 299 (!!surface_layer_bridge_); |
300 } | 300 } |
301 | 301 |
302 bool HTMLCanvasElement::IsPaintable() const { | 302 bool HTMLCanvasElement::IsPaintable() const { |
303 return (context_ && context_->IsPaintable()) || | 303 return (context_ && context_->IsPaintable()) || |
304 ImageBuffer::CanCreateImageBuffer(Size()); | 304 ImageBuffer::CanCreateImageBuffer(Size()); |
305 } | 305 } |
306 | 306 |
307 bool HTMLCanvasElement::IsAccelerated() const { | 307 bool HTMLCanvasElement::IsAccelerated() const { |
308 return context_ && context_->IsAccelerated(); | 308 return context_ && context_->IsAccelerated(); |
309 } | 309 } |
310 | 310 |
311 void HTMLCanvasElement::DidDraw(const FloatRect& rect) { | 311 void HTMLCanvasElement::DidDraw(const FloatRect& rect) { |
312 if (rect.IsEmpty()) | 312 if (rect.IsEmpty()) |
313 return; | 313 return; |
314 image_buffer_is_clear_ = false; | 314 image_buffer_is_clear_ = false; |
315 ClearCopiedImage(); | 315 ClearCopiedImage(); |
316 if (GetLayoutObject()) | 316 if (GetLayoutObject()) |
317 GetLayoutObject()->SetMayNeedPaintInvalidation(); | 317 GetLayoutObject()->SetMayNeedPaintInvalidation(); |
318 if (Is2d() && context_->ShouldAntialias() && GetPage() && | 318 if (Is2d() && context_->ShouldAntialias() && GetPage() && |
319 GetPage()->DeviceScaleFactorDeprecated() > 1.0f) { | 319 GetPage()->DeviceScaleFactorDeprecated() > 1.0f) { |
320 FloatRect inflated_rect = rect; | 320 FloatRect inflated_rect = rect; |
321 inflated_rect.Inflate(1); | 321 inflated_rect.Inflate(1); |
322 dirty_rect_.Unite(inflated_rect); | 322 dirty_rect_.Unite(inflated_rect); |
323 } else { | 323 } else { |
324 dirty_rect_.Unite(rect); | 324 dirty_rect_.Unite(rect); |
325 } | 325 } |
326 if (Is2d() && HasImageBuffer()) | 326 if (Is2d() && GetImageBuffer()) |
327 Buffer()->DidDraw(rect); | 327 GetImageBuffer()->DidDraw(rect); |
328 } | 328 } |
329 | 329 |
330 void HTMLCanvasElement::DidDraw() { | 330 void HTMLCanvasElement::DidDraw() { |
331 DidDraw(FloatRect(0, 0, Size().Width(), Size().Height())); | 331 DidDraw(FloatRect(0, 0, Size().Width(), Size().Height())); |
332 } | 332 } |
333 | 333 |
334 void HTMLCanvasElement::FinalizeFrame() { | 334 void HTMLCanvasElement::FinalizeFrame() { |
335 if (HasImageBuffer()) | 335 if (GetImageBuffer()) |
336 image_buffer_->FinalizeFrame(); | 336 image_buffer_->FinalizeFrame(); |
337 | 337 |
338 // If the canvas is visible, notifying listeners is taken | 338 // If the canvas is visible, notifying listeners is taken |
339 // care of in the in doDeferredPaintInvalidation, which allows | 339 // care of in the in doDeferredPaintInvalidation, which allows |
340 // the frame to be grabbed prior to compositing, which is | 340 // the frame to be grabbed prior to compositing, which is |
341 // critically important because compositing may clear the canvas's | 341 // critically important because compositing may clear the canvas's |
342 // image. (e.g. WebGL context with preserveDrawingBuffer=false). | 342 // image. (e.g. WebGL context with preserveDrawingBuffer=false). |
343 // If the canvas is not visible, doDeferredPaintInvalidation | 343 // If the canvas is not visible, doDeferredPaintInvalidation |
344 // will not get called, so we need to take care of business here. | 344 // will not get called, so we need to take care of business here. |
345 if (!did_notify_listeners_for_current_frame_) | 345 if (!did_notify_listeners_for_current_frame_) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 mapped_dirty_rect.Move(-lb->ContentBoxOffset()); | 380 mapped_dirty_rect.Move(-lb->ContentBoxOffset()); |
381 } | 381 } |
382 invalidation_rect = mapped_dirty_rect; | 382 invalidation_rect = mapped_dirty_rect; |
383 } else { | 383 } else { |
384 invalidation_rect = dirty_rect_; | 384 invalidation_rect = dirty_rect_; |
385 } | 385 } |
386 | 386 |
387 if (dirty_rect_.IsEmpty()) | 387 if (dirty_rect_.IsEmpty()) |
388 return; | 388 return; |
389 | 389 |
390 if (HasImageBuffer()) { | 390 if (GetImageBuffer()) { |
391 image_buffer_->DoPaintInvalidation(invalidation_rect); | 391 image_buffer_->DoPaintInvalidation(invalidation_rect); |
392 } | 392 } |
393 } | 393 } |
394 | 394 |
395 if (context_->GetContextType() == | 395 if (context_->GetContextType() == |
396 CanvasRenderingContext::kContextImageBitmap && | 396 CanvasRenderingContext::kContextImageBitmap && |
397 context_->PlatformLayer()) { | 397 context_->PlatformLayer()) { |
398 context_->PlatformLayer()->Invalidate(); | 398 context_->PlatformLayer()->Invalidate(); |
399 } | 399 } |
400 | 400 |
(...skipping 24 matching lines...) Expand all Loading... |
425 // FIXME: is this invalidation using the correct compositing state? | 425 // FIXME: is this invalidation using the correct compositing state? |
426 DisableCompositingQueryAsserts disabler; | 426 DisableCompositingQueryAsserts disabler; |
427 ro->InvalidatePaintRectangle(mapped_dirty_rect); | 427 ro->InvalidatePaintRectangle(mapped_dirty_rect); |
428 } | 428 } |
429 dirty_rect_ = FloatRect(); | 429 dirty_rect_ = FloatRect(); |
430 | 430 |
431 num_frames_since_last_rendering_mode_switch_++; | 431 num_frames_since_last_rendering_mode_switch_++; |
432 if (RuntimeEnabledFeatures:: | 432 if (RuntimeEnabledFeatures:: |
433 enableCanvas2dDynamicRenderingModeSwitchingEnabled() && | 433 enableCanvas2dDynamicRenderingModeSwitchingEnabled() && |
434 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) { | 434 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) { |
435 if (Is2d() && HasImageBuffer() && Buffer()->IsAccelerated() && | 435 if (Is2d() && GetImageBuffer() && GetImageBuffer()->IsAccelerated() && |
436 num_frames_since_last_rendering_mode_switch_ >= | 436 num_frames_since_last_rendering_mode_switch_ >= |
437 ExpensiveCanvasHeuristicParameters::kMinFramesBeforeSwitch && | 437 ExpensiveCanvasHeuristicParameters::kMinFramesBeforeSwitch && |
438 !pending_rendering_mode_switch_) { | 438 !pending_rendering_mode_switch_) { |
439 if (!context_->IsAccelerationOptimalForCanvasContent()) { | 439 if (!context_->IsAccelerationOptimalForCanvasContent()) { |
440 // The switch must be done asynchronously in order to avoid switching | 440 // The switch must be done asynchronously in order to avoid switching |
441 // during the paint invalidation step. | 441 // during the paint invalidation step. |
442 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( | 442 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( |
443 BLINK_FROM_HERE, | 443 BLINK_FROM_HERE, |
444 WTF::Bind( | 444 WTF::Bind( |
445 [](WeakPtr<ImageBuffer> buffer) { | 445 [](WeakPtr<ImageBuffer> buffer) { |
446 if (buffer) { | 446 if (buffer) { |
447 buffer->DisableAcceleration(); | 447 buffer->DisableAcceleration(); |
448 } | 448 } |
449 }, | 449 }, |
450 image_buffer_->weak_ptr_factory_.CreateWeakPtr())); | 450 image_buffer_->weak_ptr_factory_.CreateWeakPtr())); |
451 num_frames_since_last_rendering_mode_switch_ = 0; | 451 num_frames_since_last_rendering_mode_switch_ = 0; |
452 pending_rendering_mode_switch_ = true; | 452 pending_rendering_mode_switch_ = true; |
453 } | 453 } |
454 } | 454 } |
455 } | 455 } |
456 | 456 |
457 if (pending_rendering_mode_switch_ && Buffer() && | 457 if (pending_rendering_mode_switch_ && GetOrCreateImageBuffer() && |
458 !Buffer()->IsAccelerated()) { | 458 !GetOrCreateImageBuffer()->IsAccelerated()) { |
459 pending_rendering_mode_switch_ = false; | 459 pending_rendering_mode_switch_ = false; |
460 } | 460 } |
461 | 461 |
462 DCHECK(dirty_rect_.IsEmpty()); | 462 DCHECK(dirty_rect_.IsEmpty()); |
463 } | 463 } |
464 | 464 |
465 void HTMLCanvasElement::Reset() { | 465 void HTMLCanvasElement::Reset() { |
466 if (ignore_reset_) | 466 if (ignore_reset_) |
467 return; | 467 return; |
468 | 468 |
469 dirty_rect_ = FloatRect(); | 469 dirty_rect_ = FloatRect(); |
470 | 470 |
471 bool ok; | 471 bool ok; |
472 bool had_image_buffer = HasImageBuffer(); | 472 bool had_image_buffer = GetImageBuffer(); |
473 | 473 |
474 int w = getAttribute(widthAttr).ToInt(&ok); | 474 int w = getAttribute(widthAttr).ToInt(&ok); |
475 if (!ok || w < 0) | 475 if (!ok || w < 0) |
476 w = kDefaultWidth; | 476 w = kDefaultWidth; |
477 | 477 |
478 int h = getAttribute(heightAttr).ToInt(&ok); | 478 int h = getAttribute(heightAttr).ToInt(&ok); |
479 if (!ok || h < 0) | 479 if (!ok || h < 0) |
480 h = kDefaultHeight; | 480 h = kDefaultHeight; |
481 | 481 |
482 if (Is2d()) | 482 if (Is2d()) |
483 context_->Reset(); | 483 context_->Reset(); |
484 | 484 |
485 IntSize old_size = Size(); | 485 IntSize old_size = Size(); |
486 IntSize new_size(w, h); | 486 IntSize new_size(w, h); |
487 | 487 |
488 // If the size of an existing buffer matches, we can just clear it instead of | 488 // If the size of an existing buffer matches, we can just clear it instead of |
489 // reallocating. This optimization is only done for 2D canvases for now. | 489 // reallocating. This optimization is only done for 2D canvases for now. |
490 if (had_image_buffer && old_size == new_size && Is2d() && | 490 if (had_image_buffer && old_size == new_size && Is2d() && |
491 !Buffer()->IsRecording()) { | 491 !GetOrCreateImageBuffer()->IsRecording()) { |
492 if (!image_buffer_is_clear_) { | 492 if (!image_buffer_is_clear_) { |
493 image_buffer_is_clear_ = true; | 493 image_buffer_is_clear_ = true; |
494 context_->clearRect(0, 0, width(), height()); | 494 context_->clearRect(0, 0, width(), height()); |
495 } | 495 } |
496 return; | 496 return; |
497 } | 497 } |
498 | 498 |
499 SetSurfaceSize(new_size); | 499 SetSurfaceSize(new_size); |
500 | 500 |
501 if (Is3d() && old_size != Size()) | 501 if (Is3d() && old_size != Size()) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 return; | 565 return; |
566 | 566 |
567 const ComputedStyle* style = EnsureComputedStyle(); | 567 const ComputedStyle* style = EnsureComputedStyle(); |
568 SkFilterQuality filter_quality = | 568 SkFilterQuality filter_quality = |
569 (style && style->ImageRendering() == kImageRenderingPixelated) | 569 (style && style->ImageRendering() == kImageRenderingPixelated) |
570 ? kNone_SkFilterQuality | 570 ? kNone_SkFilterQuality |
571 : kLow_SkFilterQuality; | 571 : kLow_SkFilterQuality; |
572 | 572 |
573 if (Is3d()) { | 573 if (Is3d()) { |
574 context_->SetFilterQuality(filter_quality); | 574 context_->SetFilterQuality(filter_quality); |
575 } else if (HasImageBuffer()) { | 575 } else if (GetImageBuffer()) { |
576 image_buffer_->SetFilterQuality(filter_quality); | 576 image_buffer_->SetFilterQuality(filter_quality); |
577 } | 577 } |
578 | 578 |
579 if (HasImageBuffer() && !image_buffer_is_clear_) | 579 if (GetImageBuffer() && !image_buffer_is_clear_) |
580 PaintTiming::From(GetDocument()).MarkFirstContentfulPaint(); | 580 PaintTiming::From(GetDocument()).MarkFirstContentfulPaint(); |
581 | 581 |
582 if (!PaintsIntoCanvasBuffer() && !GetDocument().Printing()) | 582 if (!PaintsIntoCanvasBuffer() && !GetDocument().Printing()) |
583 return; | 583 return; |
584 | 584 |
585 if (PlaceholderFrame()) { | 585 if (PlaceholderFrame()) { |
586 DCHECK(GetDocument().Printing()); | 586 DCHECK(GetDocument().Printing()); |
587 context.DrawImage(PlaceholderFrame().Get(), PixelSnappedIntRect(r)); | 587 context.DrawImage(PlaceholderFrame().Get(), PixelSnappedIntRect(r)); |
588 return; | 588 return; |
589 } | 589 } |
590 | 590 |
591 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts. | 591 // TODO(junov): Paint is currently only implemented by ImageBitmap contexts. |
592 // We could improve the abstraction by making all context types paint | 592 // We could improve the abstraction by making all context types paint |
593 // themselves (implement paint()). | 593 // themselves (implement paint()). |
594 if (context_->Paint(context, PixelSnappedIntRect(r))) | 594 if (context_->Paint(context, PixelSnappedIntRect(r))) |
595 return; | 595 return; |
596 | 596 |
597 context_->PaintRenderingResultsToCanvas(kFrontBuffer); | 597 context_->PaintRenderingResultsToCanvas(kFrontBuffer); |
598 if (HasImageBuffer()) { | 598 if (GetImageBuffer()) { |
599 if (!context.ContextDisabled()) { | 599 if (!context.ContextDisabled()) { |
600 SkBlendMode composite_operator = | 600 SkBlendMode composite_operator = |
601 !context_ || context_->CreationAttributes().alpha() | 601 !context_ || context_->CreationAttributes().alpha() |
602 ? SkBlendMode::kSrcOver | 602 ? SkBlendMode::kSrcOver |
603 : SkBlendMode::kSrc; | 603 : SkBlendMode::kSrc; |
604 Buffer()->Draw(context, PixelSnappedIntRect(r), 0, composite_operator); | 604 GetImageBuffer()->Draw(context, PixelSnappedIntRect(r), 0, |
| 605 composite_operator); |
605 } | 606 } |
606 } else { | 607 } else { |
607 // When alpha is false, we should draw to opaque black. | 608 // When alpha is false, we should draw to opaque black. |
608 if (!context_->CreationAttributes().alpha()) | 609 if (!context_->CreationAttributes().alpha()) |
609 context.FillRect(FloatRect(r), Color(0, 0, 0)); | 610 context.FillRect(FloatRect(r), Color(0, 0, 0)); |
610 } | 611 } |
611 | 612 |
612 if (Is3d() && PaintsIntoCanvasBuffer()) | 613 if (Is3d() && PaintsIntoCanvasBuffer()) |
613 context_->MarkLayerComposited(); | 614 context_->MarkLayerComposited(); |
614 } | 615 } |
615 | 616 |
616 bool HTMLCanvasElement::Is3d() const { | 617 bool HTMLCanvasElement::Is3d() const { |
617 return context_ && context_->Is3d(); | 618 return context_ && context_->Is3d(); |
618 } | 619 } |
619 | 620 |
620 bool HTMLCanvasElement::Is2d() const { | 621 bool HTMLCanvasElement::Is2d() const { |
621 return context_ && context_->Is2d(); | 622 return context_ && context_->Is2d(); |
622 } | 623 } |
623 | 624 |
624 bool HTMLCanvasElement::IsAnimated2d() const { | 625 bool HTMLCanvasElement::IsAnimated2d() const { |
625 return Is2d() && HasImageBuffer() && image_buffer_->WasDrawnToAfterSnapshot(); | 626 return Is2d() && GetImageBuffer() && |
| 627 GetImageBuffer()->WasDrawnToAfterSnapshot(); |
626 } | 628 } |
627 | 629 |
628 void HTMLCanvasElement::SetSurfaceSize(const IntSize& size) { | 630 void HTMLCanvasElement::SetSurfaceSize(const IntSize& size) { |
629 size_ = size; | 631 size_ = size; |
630 did_fail_to_create_image_buffer_ = false; | 632 did_fail_to_create_image_buffer_ = false; |
631 DiscardImageBuffer(); | 633 DiscardImageBuffer(); |
632 ClearCopiedImage(); | 634 ClearCopiedImage(); |
633 if (Is2d() && context_->isContextLost()) { | 635 if (Is2d() && context_->isContextLost()) { |
634 context_->DidSetSurfaceSize(); | 636 context_->DidSetSurfaceSize(); |
635 } | 637 } |
636 } | 638 } |
637 | 639 |
638 const AtomicString HTMLCanvasElement::ImageSourceURL() const { | 640 const AtomicString HTMLCanvasElement::ImageSourceURL() const { |
639 return AtomicString( | 641 return AtomicString( |
640 ToDataURLInternal(ImageEncoderUtils::kDefaultMimeType, 0, kFrontBuffer)); | 642 ToDataURLInternal(ImageEncoderUtils::kDefaultMimeType, 0, kFrontBuffer)); |
641 } | 643 } |
642 | 644 |
643 void HTMLCanvasElement::PrepareSurfaceForPaintingIfNeeded() const { | 645 void HTMLCanvasElement::PrepareSurfaceForPaintingIfNeeded() { |
644 DCHECK(Is2d()); // This function is called by the 2d context | 646 DCHECK(Is2d()); // This function is called by the 2d context |
645 if (Buffer()) | 647 if (GetOrCreateImageBuffer()) |
646 image_buffer_->PrepareSurfaceForPaintingIfNeeded(); | 648 image_buffer_->PrepareSurfaceForPaintingIfNeeded(); |
647 } | 649 } |
648 | 650 |
649 ImageData* HTMLCanvasElement::ToImageData(SourceDrawingBuffer source_buffer, | 651 ImageData* HTMLCanvasElement::ToImageData(SourceDrawingBuffer source_buffer, |
650 SnapshotReason reason) const { | 652 SnapshotReason reason) const { |
651 ImageData* image_data; | 653 ImageData* image_data; |
652 if (Is3d()) { | 654 if (Is3d()) { |
653 // Get non-premultiplied data because of inaccurate premultiplied alpha | 655 // Get non-premultiplied data because of inaccurate premultiplied alpha |
654 // conversion of buffer()->toDataURL(). | 656 // conversion of buffer()->toDataURL(). |
655 image_data = context_->PaintRenderingResultsToImageData(source_buffer); | 657 image_data = context_->PaintRenderingResultsToImageData(source_buffer); |
656 if (image_data) | 658 if (image_data) |
657 return image_data; | 659 return image_data; |
658 | 660 |
659 context_->PaintRenderingResultsToCanvas(source_buffer); | 661 context_->PaintRenderingResultsToCanvas(source_buffer); |
660 image_data = ImageData::Create(size_); | 662 image_data = ImageData::Create(size_); |
661 if (image_data && HasImageBuffer()) { | 663 if (image_data && GetImageBuffer()) { |
662 sk_sp<SkImage> snapshot = | 664 sk_sp<SkImage> snapshot = |
663 Buffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason); | 665 GetImageBuffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason); |
664 if (snapshot) { | 666 if (snapshot) { |
665 SkImageInfo image_info = SkImageInfo::Make( | 667 SkImageInfo image_info = SkImageInfo::Make( |
666 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); | 668 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); |
667 snapshot->readPixels(image_info, image_data->data()->Data(), | 669 snapshot->readPixels(image_info, image_data->data()->Data(), |
668 image_info.minRowBytes(), 0, 0); | 670 image_info.minRowBytes(), 0, 0); |
669 } | 671 } |
670 } | 672 } |
671 return image_data; | 673 return image_data; |
672 } | 674 } |
673 | 675 |
674 image_data = ImageData::Create(size_); | 676 image_data = ImageData::Create(size_); |
675 | 677 |
676 if ((!context_ || !image_data) && !PlaceholderFrame()) | 678 if ((!context_ || !image_data) && !PlaceholderFrame()) |
677 return image_data; | 679 return image_data; |
678 | 680 |
679 DCHECK(Is2d() || PlaceholderFrame()); | 681 DCHECK(Is2d() || PlaceholderFrame()); |
680 sk_sp<SkImage> snapshot; | 682 sk_sp<SkImage> snapshot; |
681 if (HasImageBuffer()) { | 683 if (GetImageBuffer()) { |
682 snapshot = Buffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason); | 684 snapshot = |
| 685 GetImageBuffer()->NewSkImageSnapshot(kPreferNoAcceleration, reason); |
683 } else if (PlaceholderFrame()) { | 686 } else if (PlaceholderFrame()) { |
684 DCHECK(PlaceholderFrame()->OriginClean()); | 687 DCHECK(PlaceholderFrame()->OriginClean()); |
685 snapshot = PlaceholderFrame()->ImageForCurrentFrame(); | 688 snapshot = PlaceholderFrame()->ImageForCurrentFrame(); |
686 } | 689 } |
687 | 690 |
688 if (snapshot) { | 691 if (snapshot) { |
689 SkImageInfo image_info = SkImageInfo::Make( | 692 SkImageInfo image_info = SkImageInfo::Make( |
690 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); | 693 width(), height(), kRGBA_8888_SkColorType, kUnpremul_SkAlphaType); |
691 snapshot->readPixels(image_info, image_data->data()->Data(), | 694 snapshot->readPixels(image_info, image_data->data()->Data(), |
692 image_info.minRowBytes(), 0, 0); | 695 image_info.minRowBytes(), 0, 0); |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 checked_externally_allocated_memory.ValueOrDefault( | 1090 checked_externally_allocated_memory.ValueOrDefault( |
1088 std::numeric_limits<intptr_t>::max()); | 1091 std::numeric_limits<intptr_t>::max()); |
1089 | 1092 |
1090 // Subtracting two intptr_t that are known to be positive will never | 1093 // Subtracting two intptr_t that are known to be positive will never |
1091 // underflow. | 1094 // underflow. |
1092 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( | 1095 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( |
1093 externally_allocated_memory - externally_allocated_memory_); | 1096 externally_allocated_memory - externally_allocated_memory_); |
1094 externally_allocated_memory_ = externally_allocated_memory; | 1097 externally_allocated_memory_ = externally_allocated_memory; |
1095 } | 1098 } |
1096 | 1099 |
1097 PaintCanvas* HTMLCanvasElement::DrawingCanvas() const { | 1100 PaintCanvas* HTMLCanvasElement::DrawingCanvas() { |
1098 return Buffer() ? image_buffer_->Canvas() : nullptr; | 1101 return GetOrCreateImageBuffer() ? GetImageBuffer()->Canvas() : nullptr; |
1099 } | 1102 } |
1100 | 1103 |
1101 void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) const { | 1104 void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) { |
1102 if (Buffer()) | 1105 if (GetOrCreateImageBuffer()) |
1103 image_buffer_->DisableDeferral(reason); | 1106 image_buffer_->DisableDeferral(reason); |
1104 } | 1107 } |
1105 | 1108 |
1106 PaintCanvas* HTMLCanvasElement::ExistingDrawingCanvas() const { | 1109 PaintCanvas* HTMLCanvasElement::ExistingDrawingCanvas() const { |
1107 if (!HasImageBuffer()) | 1110 if (!GetImageBuffer()) |
1108 return nullptr; | 1111 return nullptr; |
1109 | 1112 |
1110 return image_buffer_->Canvas(); | 1113 return image_buffer_->Canvas(); |
1111 } | 1114 } |
1112 | 1115 |
1113 ImageBuffer* HTMLCanvasElement::Buffer() const { | 1116 ImageBuffer* HTMLCanvasElement::GetOrCreateImageBuffer() { |
1114 DCHECK(context_); | 1117 DCHECK(context_); |
1115 DCHECK(context_->GetContextType() != | 1118 DCHECK(context_->GetContextType() != |
1116 CanvasRenderingContext::kContextImageBitmap); | 1119 CanvasRenderingContext::kContextImageBitmap); |
1117 if (!HasImageBuffer() && !did_fail_to_create_image_buffer_) | 1120 if (!image_buffer_ && !did_fail_to_create_image_buffer_) |
1118 const_cast<HTMLCanvasElement*>(this)->CreateImageBuffer(); | 1121 CreateImageBuffer(); |
1119 return image_buffer_.get(); | 1122 return image_buffer_.get(); |
1120 } | 1123 } |
1121 | 1124 |
1122 void HTMLCanvasElement::CreateImageBufferUsingSurfaceForTesting( | 1125 void HTMLCanvasElement::CreateImageBufferUsingSurfaceForTesting( |
1123 std::unique_ptr<ImageBufferSurface> surface) { | 1126 std::unique_ptr<ImageBufferSurface> surface) { |
1124 DiscardImageBuffer(); | 1127 DiscardImageBuffer(); |
1125 SetIntegralAttribute(widthAttr, surface->size().Width()); | 1128 SetIntegralAttribute(widthAttr, surface->size().Width()); |
1126 SetIntegralAttribute(heightAttr, surface->size().Height()); | 1129 SetIntegralAttribute(heightAttr, surface->size().Height()); |
1127 CreateImageBufferInternal(std::move(surface)); | 1130 CreateImageBufferInternal(std::move(surface)); |
1128 } | 1131 } |
1129 | 1132 |
1130 void HTMLCanvasElement::EnsureUnacceleratedImageBuffer() { | 1133 void HTMLCanvasElement::EnsureUnacceleratedImageBuffer() { |
1131 DCHECK(context_); | 1134 DCHECK(context_); |
1132 if ((HasImageBuffer() && !image_buffer_->IsAccelerated()) || | 1135 if ((GetImageBuffer() && !GetImageBuffer()->IsAccelerated()) || |
1133 did_fail_to_create_image_buffer_) | 1136 did_fail_to_create_image_buffer_) |
1134 return; | 1137 return; |
1135 DiscardImageBuffer(); | 1138 DiscardImageBuffer(); |
1136 OpacityMode opacity_mode = | 1139 OpacityMode opacity_mode = |
1137 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque; | 1140 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque; |
1138 image_buffer_ = ImageBuffer::Create(Size(), opacity_mode); | 1141 image_buffer_ = ImageBuffer::Create(Size(), opacity_mode); |
1139 did_fail_to_create_image_buffer_ = !image_buffer_; | 1142 did_fail_to_create_image_buffer_ = !image_buffer_; |
1140 } | 1143 } |
1141 | 1144 |
1142 PassRefPtr<Image> HTMLCanvasElement::CopiedImage( | 1145 PassRefPtr<Image> HTMLCanvasElement::CopiedImage( |
1143 SourceDrawingBuffer source_buffer, | 1146 SourceDrawingBuffer source_buffer, |
1144 AccelerationHint hint, | 1147 AccelerationHint hint, |
1145 SnapshotReason snapshot_reason) const { | 1148 SnapshotReason snapshot_reason) { |
1146 if (!IsPaintable()) | 1149 if (!IsPaintable()) |
1147 return nullptr; | 1150 return nullptr; |
1148 if (!context_) | 1151 if (!context_) |
1149 return CreateTransparentImage(Size()); | 1152 return CreateTransparentImage(Size()); |
1150 | 1153 |
1151 if (context_->GetContextType() == | 1154 if (context_->GetContextType() == |
1152 CanvasRenderingContext::kContextImageBitmap) { | 1155 CanvasRenderingContext::kContextImageBitmap) { |
1153 RefPtr<Image> image = context_->GetImage(hint, snapshot_reason); | 1156 RefPtr<Image> image = context_->GetImage(hint, snapshot_reason); |
| 1157 // TODO(fserb): return image? |
1154 if (image) | 1158 if (image) |
1155 return context_->GetImage(hint, snapshot_reason); | 1159 return context_->GetImage(hint, snapshot_reason); |
1156 // Special case: transferFromImageBitmap is not yet called. | 1160 // Special case: transferFromImageBitmap is not yet called. |
1157 sk_sp<SkSurface> surface = | 1161 sk_sp<SkSurface> surface = |
1158 SkSurface::MakeRasterN32Premul(width(), height()); | 1162 SkSurface::MakeRasterN32Premul(width(), height()); |
1159 return StaticBitmapImage::Create(surface->makeImageSnapshot()); | 1163 return StaticBitmapImage::Create(surface->makeImageSnapshot()); |
1160 } | 1164 } |
1161 | 1165 |
1162 bool need_to_update = !copied_image_; | 1166 bool need_to_update = !copied_image_; |
1163 // The concept of SourceDrawingBuffer is valid on only WebGL. | 1167 // The concept of SourceDrawingBuffer is valid on only WebGL. |
1164 if (context_->Is3d()) | 1168 if (context_->Is3d()) |
1165 need_to_update |= context_->PaintRenderingResultsToCanvas(source_buffer); | 1169 need_to_update |= context_->PaintRenderingResultsToCanvas(source_buffer); |
1166 if (need_to_update && Buffer()) { | 1170 if (need_to_update && GetOrCreateImageBuffer()) { |
1167 copied_image_ = Buffer()->NewImageSnapshot(hint, snapshot_reason); | 1171 copied_image_ = GetImageBuffer()->NewImageSnapshot(hint, snapshot_reason); |
1168 UpdateExternallyAllocatedMemory(); | 1172 UpdateExternallyAllocatedMemory(); |
1169 } | 1173 } |
1170 return copied_image_; | 1174 return copied_image_; |
1171 } | 1175 } |
1172 | 1176 |
1173 void HTMLCanvasElement::DiscardImageBuffer() { | 1177 void HTMLCanvasElement::DiscardImageBuffer() { |
1174 image_buffer_.reset(); | 1178 image_buffer_.reset(); |
1175 dirty_rect_ = FloatRect(); | 1179 dirty_rect_ = FloatRect(); |
1176 UpdateExternallyAllocatedMemory(); | 1180 UpdateExternallyAllocatedMemory(); |
1177 } | 1181 } |
1178 | 1182 |
1179 void HTMLCanvasElement::ClearCopiedImage() { | 1183 void HTMLCanvasElement::ClearCopiedImage() { |
1180 if (copied_image_) { | 1184 if (copied_image_) { |
1181 copied_image_.Clear(); | 1185 copied_image_.Clear(); |
1182 UpdateExternallyAllocatedMemory(); | 1186 UpdateExternallyAllocatedMemory(); |
1183 } | 1187 } |
1184 } | 1188 } |
1185 | 1189 |
1186 AffineTransform HTMLCanvasElement::BaseTransform() const { | 1190 AffineTransform HTMLCanvasElement::BaseTransform() const { |
1187 DCHECK(HasImageBuffer() && !did_fail_to_create_image_buffer_); | 1191 DCHECK(GetImageBuffer() && !did_fail_to_create_image_buffer_); |
1188 return image_buffer_->BaseTransform(); | 1192 return image_buffer_->BaseTransform(); |
1189 } | 1193 } |
1190 | 1194 |
1191 void HTMLCanvasElement::PageVisibilityChanged() { | 1195 void HTMLCanvasElement::PageVisibilityChanged() { |
1192 if (!context_) | 1196 if (!context_) |
1193 return; | 1197 return; |
1194 | 1198 |
1195 bool hidden = !GetPage()->IsPageVisible(); | 1199 bool hidden = !GetPage()->IsPageVisible(); |
1196 context_->SetIsHidden(hidden); | 1200 context_->SetIsHidden(hidden); |
1197 if (hidden) { | 1201 if (hidden) { |
(...skipping 17 matching lines...) Expand all Loading... |
1215 | 1219 |
1216 void HTMLCanvasElement::DidMoveToNewDocument(Document& old_document) { | 1220 void HTMLCanvasElement::DidMoveToNewDocument(Document& old_document) { |
1217 ContextLifecycleObserver::SetContext(&GetDocument()); | 1221 ContextLifecycleObserver::SetContext(&GetDocument()); |
1218 PageVisibilityObserver::SetContext(GetDocument().GetPage()); | 1222 PageVisibilityObserver::SetContext(GetDocument().GetPage()); |
1219 HTMLElement::DidMoveToNewDocument(old_document); | 1223 HTMLElement::DidMoveToNewDocument(old_document); |
1220 } | 1224 } |
1221 | 1225 |
1222 void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) { | 1226 void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) { |
1223 if (ExpensiveCanvasHeuristicParameters::kEnableAccelerationToAvoidReadbacks && | 1227 if (ExpensiveCanvasHeuristicParameters::kEnableAccelerationToAvoidReadbacks && |
1224 SharedGpuContext::AllowSoftwareToAcceleratedCanvasUpgrade() && | 1228 SharedGpuContext::AllowSoftwareToAcceleratedCanvasUpgrade() && |
1225 source->IsAccelerated() && !Buffer()->IsAccelerated() && | 1229 source->IsAccelerated() && !GetOrCreateImageBuffer()->IsAccelerated() && |
1226 ShouldAccelerate(kIgnoreResourceLimitCriteria)) { | 1230 ShouldAccelerate(kIgnoreResourceLimitCriteria)) { |
1227 OpacityMode opacity_mode = | 1231 OpacityMode opacity_mode = |
1228 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque; | 1232 context_->CreationAttributes().alpha() ? kNonOpaque : kOpaque; |
1229 int msaa_sample_count = 0; | 1233 int msaa_sample_count = 0; |
1230 std::unique_ptr<ImageBufferSurface> surface = | 1234 std::unique_ptr<ImageBufferSurface> surface = |
1231 CreateAcceleratedImageBufferSurface(opacity_mode, &msaa_sample_count); | 1235 CreateAcceleratedImageBufferSurface(opacity_mode, &msaa_sample_count); |
1232 if (surface) { | 1236 if (surface) { |
1233 Buffer()->SetSurface(std::move(surface)); | 1237 GetOrCreateImageBuffer()->SetSurface(std::move(surface)); |
1234 SetNeedsCompositingUpdate(); | 1238 SetNeedsCompositingUpdate(); |
1235 } | 1239 } |
1236 } | 1240 } |
1237 } | 1241 } |
1238 | 1242 |
1239 PassRefPtr<Image> HTMLCanvasElement::GetSourceImageForCanvas( | 1243 PassRefPtr<Image> HTMLCanvasElement::GetSourceImageForCanvas( |
1240 SourceImageStatus* status, | 1244 SourceImageStatus* status, |
1241 AccelerationHint hint, | 1245 AccelerationHint hint, |
1242 SnapshotReason reason, | 1246 SnapshotReason reason, |
1243 const FloatSize&) const { | 1247 const FloatSize&) { |
1244 if (!width() || !height()) { | 1248 if (!width() || !height()) { |
1245 *status = kZeroSizeCanvasSourceImageStatus; | 1249 *status = kZeroSizeCanvasSourceImageStatus; |
1246 return nullptr; | 1250 return nullptr; |
1247 } | 1251 } |
1248 | 1252 |
1249 if (!IsPaintable()) { | 1253 if (!IsPaintable()) { |
1250 *status = kInvalidSourceImageStatus; | 1254 *status = kInvalidSourceImageStatus; |
1251 return nullptr; | 1255 return nullptr; |
1252 } | 1256 } |
1253 | 1257 |
(...skipping 15 matching lines...) Expand all Loading... |
1269 } | 1273 } |
1270 | 1274 |
1271 sk_sp<SkImage> sk_image; | 1275 sk_sp<SkImage> sk_image; |
1272 // TODO(ccameron): Canvas should produce sRGB images. | 1276 // TODO(ccameron): Canvas should produce sRGB images. |
1273 // https://crbug.com/672299 | 1277 // https://crbug.com/672299 |
1274 if (Is3d()) { | 1278 if (Is3d()) { |
1275 // Because WebGL sources always require making a copy of the back buffer, we | 1279 // Because WebGL sources always require making a copy of the back buffer, we |
1276 // use paintRenderingResultsToCanvas instead of getImage in order to keep a | 1280 // use paintRenderingResultsToCanvas instead of getImage in order to keep a |
1277 // cached copy of the backing in the canvas's ImageBuffer. | 1281 // cached copy of the backing in the canvas's ImageBuffer. |
1278 RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer); | 1282 RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer); |
1279 if (HasImageBuffer()) { | 1283 if (GetImageBuffer()) { |
1280 sk_image = Buffer()->NewSkImageSnapshot(hint, reason); | 1284 sk_image = GetImageBuffer()->NewSkImageSnapshot(hint, reason); |
1281 } else { | 1285 } else { |
1282 sk_image = CreateTransparentSkImage(Size()); | 1286 sk_image = CreateTransparentSkImage(Size()); |
1283 } | 1287 } |
1284 } else { | 1288 } else { |
1285 if (ExpensiveCanvasHeuristicParameters:: | 1289 if (ExpensiveCanvasHeuristicParameters:: |
1286 kDisableAccelerationToAvoidReadbacks && | 1290 kDisableAccelerationToAvoidReadbacks && |
1287 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() && | 1291 !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() && |
1288 hint == kPreferNoAcceleration && HasImageBuffer() && | 1292 hint == kPreferNoAcceleration && GetImageBuffer() && |
1289 Buffer()->IsAccelerated()) { | 1293 GetImageBuffer()->IsAccelerated()) { |
1290 Buffer()->DisableAcceleration(); | 1294 GetImageBuffer()->DisableAcceleration(); |
1291 } | 1295 } |
1292 RefPtr<Image> image = RenderingContext()->GetImage(hint, reason); | 1296 RefPtr<Image> image = RenderingContext()->GetImage(hint, reason); |
1293 if (image) { | 1297 if (image) { |
1294 sk_image = image->ImageForCurrentFrame(); | 1298 sk_image = image->ImageForCurrentFrame(); |
1295 } else { | 1299 } else { |
1296 sk_image = CreateTransparentSkImage(Size()); | 1300 sk_image = CreateTransparentSkImage(Size()); |
1297 } | 1301 } |
1298 } | 1302 } |
1299 | 1303 |
1300 if (sk_image) { | 1304 if (sk_image) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 // Creates a placeholder layer first before Surface is created. | 1463 // Creates a placeholder layer first before Surface is created. |
1460 surface_layer_bridge_->CreateSolidColorLayer(); | 1464 surface_layer_bridge_->CreateSolidColorLayer(); |
1461 } | 1465 } |
1462 } | 1466 } |
1463 | 1467 |
1464 void HTMLCanvasElement::OnWebLayerReplaced() { | 1468 void HTMLCanvasElement::OnWebLayerReplaced() { |
1465 SetNeedsCompositingUpdate(); | 1469 SetNeedsCompositingUpdate(); |
1466 } | 1470 } |
1467 | 1471 |
1468 } // namespace blink | 1472 } // namespace blink |
OLD | NEW |