| 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 |