| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/canvas2d/CanvasRenderingContext2D.h" | 5 #include "modules/canvas2d/CanvasRenderingContext2D.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include "bindings/core/v8/V8BindingForCore.h" | 8 #include "bindings/core/v8/V8BindingForCore.h" |
| 9 #include "bindings/core/v8/V8BindingForTesting.h" | 9 #include "bindings/core/v8/V8BindingForTesting.h" |
| 10 #include "core/dom/Document.h" | 10 #include "core/dom/Document.h" |
| 11 #include "core/frame/FrameView.h" | 11 #include "core/frame/FrameView.h" |
| 12 #include "core/frame/ImageBitmap.h" | 12 #include "core/frame/ImageBitmap.h" |
| 13 #include "core/frame/Settings.h" | 13 #include "core/frame/Settings.h" |
| 14 #include "core/html/HTMLCanvasElement.h" | 14 #include "core/html/HTMLCanvasElement.h" |
| 15 #include "core/html/ImageData.h" | 15 #include "core/html/ImageData.h" |
| 16 #include "core/imagebitmap/ImageBitmapOptions.h" | 16 #include "core/imagebitmap/ImageBitmapOptions.h" |
| 17 #include "core/layout/LayoutBoxModelObject.h" | 17 #include "core/layout/LayoutBoxModelObject.h" |
| 18 #include "core/loader/EmptyClients.h" | 18 #include "core/loader/EmptyClients.h" |
| 19 #include "core/paint/PaintLayer.h" | 19 #include "core/paint/PaintLayer.h" |
| 20 #include "core/testing/DummyPageHolder.h" | 20 #include "core/testing/DummyPageHolder.h" |
| 21 #include "modules/canvas2d/CanvasGradient.h" | 21 #include "modules/canvas2d/CanvasGradient.h" |
| 22 #include "modules/canvas2d/CanvasPattern.h" | 22 #include "modules/canvas2d/CanvasPattern.h" |
| 23 #include "modules/webgl/WebGLRenderingContext.h" | 23 #include "modules/webgl/WebGLRenderingContext.h" |
| 24 #include "platform/graphics/Canvas2DImageBufferSurface.h" | 24 #include "platform/graphics/Canvas2DImageBufferSurface.h" |
| 25 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | 25 #include "platform/graphics/CanvasHeuristicParameters.h" |
| 26 #include "platform/graphics/RecordingImageBufferSurface.h" | 26 #include "platform/graphics/RecordingImageBufferSurface.h" |
| 27 #include "platform/graphics/StaticBitmapImage.h" | 27 #include "platform/graphics/StaticBitmapImage.h" |
| 28 #include "platform/graphics/UnacceleratedImageBufferSurface.h" | 28 #include "platform/graphics/UnacceleratedImageBufferSurface.h" |
| 29 #include "platform/graphics/test/FakeGLES2Interface.h" | 29 #include "platform/graphics/test/FakeGLES2Interface.h" |
| 30 #include "platform/graphics/test/FakeWebGraphicsContext3DProvider.h" | 30 #include "platform/graphics/test/FakeWebGraphicsContext3DProvider.h" |
| 31 #include "platform/loader/fetch/MemoryCache.h" | 31 #include "platform/loader/fetch/MemoryCache.h" |
| 32 #include "platform/testing/TestingPlatformSupport.h" | 32 #include "platform/testing/TestingPlatformSupport.h" |
| 33 #include "platform/wtf/PtrUtil.h" | 33 #include "platform/wtf/PtrUtil.h" |
| 34 #include "public/platform/scheduler/test/renderer_scheduler_test_support.h" | 34 #include "public/platform/scheduler/test/renderer_scheduler_test_support.h" |
| 35 #include "testing/gmock/include/gmock/gmock.h" | 35 #include "testing/gmock/include/gmock/gmock.h" |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 | 530 |
| 531 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionUnderOverdrawLimit) { | 531 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionUnderOverdrawLimit) { |
| 532 CreateContext(kNonOpaque); | 532 CreateContext(kNonOpaque); |
| 533 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 533 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 534 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 534 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 535 auto* surface_ptr = surface.get(); | 535 auto* surface_ptr = surface.get(); |
| 536 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 536 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 537 | 537 |
| 538 Context2d()->setGlobalAlpha(0.5f); // To prevent overdraw optimization | 538 Context2d()->setGlobalAlpha(0.5f); // To prevent overdraw optimization |
| 539 for (int i = 0; | 539 for (int i = 0; |
| 540 i < ExpensiveCanvasHeuristicParameters::kExpensiveOverdrawThreshold - 1; | 540 i < CanvasHeuristicParameters::kExpensiveOverdrawThreshold - 1; i++) { |
| 541 i++) { | |
| 542 Context2d()->fillRect(0, 0, 10, 10); | 541 Context2d()->fillRect(0, 0, 10, 10); |
| 543 } | 542 } |
| 544 | 543 |
| 545 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); | 544 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); |
| 546 EXPECT_TRUE(surface_ptr->IsRecording()); | 545 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 547 } | 546 } |
| 548 | 547 |
| 549 TEST_F(CanvasRenderingContext2DTest, LayerPromotionOverOverdrawLimit) { | 548 TEST_F(CanvasRenderingContext2DTest, LayerPromotionOverOverdrawLimit) { |
| 550 CreateContext(kNonOpaque); | 549 CreateContext(kNonOpaque); |
| 551 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 550 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 552 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 551 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 553 auto* surface_ptr = surface.get(); | 552 auto* surface_ptr = surface.get(); |
| 554 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 553 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 555 | 554 |
| 556 Context2d()->setGlobalAlpha(0.5f); // To prevent overdraw optimization | 555 Context2d()->setGlobalAlpha(0.5f); // To prevent overdraw optimization |
| 557 for (int i = 0; | 556 for (int i = 0; i < CanvasHeuristicParameters::kExpensiveOverdrawThreshold; |
| 558 i < ExpensiveCanvasHeuristicParameters::kExpensiveOverdrawThreshold; | |
| 559 i++) { | 557 i++) { |
| 560 Context2d()->fillRect(0, 0, 10, 10); | 558 Context2d()->fillRect(0, 0, 10, 10); |
| 561 } | 559 } |
| 562 | 560 |
| 563 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); | 561 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); |
| 564 EXPECT_TRUE(surface_ptr->IsRecording()); | 562 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 565 } | 563 } |
| 566 | 564 |
| 567 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionUnderImageSizeRatioLimit) { | 565 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionUnderImageSizeRatioLimit) { |
| 568 CreateContext(kNonOpaque); | 566 CreateContext(kNonOpaque); |
| 569 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 567 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 570 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 568 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 571 auto* surface_ptr = surface.get(); | 569 auto* surface_ptr = surface.get(); |
| 572 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 570 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 573 | 571 |
| 574 NonThrowableExceptionState exception_state; | 572 NonThrowableExceptionState exception_state; |
| 575 Element* source_canvas_element = | 573 Element* source_canvas_element = |
| 576 GetDocument().createElement("canvas", exception_state); | 574 GetDocument().createElement("canvas", exception_state); |
| 577 EXPECT_FALSE(exception_state.HadException()); | 575 EXPECT_FALSE(exception_state.HadException()); |
| 578 HTMLCanvasElement* source_canvas = | 576 HTMLCanvasElement* source_canvas = |
| 579 static_cast<HTMLCanvasElement*>(source_canvas_element); | 577 static_cast<HTMLCanvasElement*>(source_canvas_element); |
| 580 IntSize source_size( | 578 IntSize source_size(10, |
| 581 10, 10 * ExpensiveCanvasHeuristicParameters::kExpensiveImageSizeRatio); | 579 10 * CanvasHeuristicParameters::kExpensiveImageSizeRatio); |
| 582 std::unique_ptr<UnacceleratedImageBufferSurface> source_surface = | 580 std::unique_ptr<UnacceleratedImageBufferSurface> source_surface = |
| 583 WTF::MakeUnique<UnacceleratedImageBufferSurface>(source_size, kNonOpaque); | 581 WTF::MakeUnique<UnacceleratedImageBufferSurface>(source_size, kNonOpaque); |
| 584 source_canvas->CreateImageBufferUsingSurfaceForTesting( | 582 source_canvas->CreateImageBufferUsingSurfaceForTesting( |
| 585 std::move(source_surface)); | 583 std::move(source_surface)); |
| 586 | 584 |
| 587 const ImageBitmapOptions default_options; | 585 const ImageBitmapOptions default_options; |
| 588 Optional<IntRect> crop_rect = IntRect(IntPoint(0, 0), source_size); | 586 Optional<IntRect> crop_rect = IntRect(IntPoint(0, 0), source_size); |
| 589 // Go through an ImageBitmap to avoid triggering a display list fallback | 587 // Go through an ImageBitmap to avoid triggering a display list fallback |
| 590 ImageBitmap* source_image_bitmap = | 588 ImageBitmap* source_image_bitmap = |
| 591 ImageBitmap::Create(source_canvas, crop_rect, default_options); | 589 ImageBitmap::Create(source_canvas, crop_rect, default_options); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 605 auto* surface_ptr = surface.get(); | 603 auto* surface_ptr = surface.get(); |
| 606 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 604 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 607 | 605 |
| 608 NonThrowableExceptionState exception_state; | 606 NonThrowableExceptionState exception_state; |
| 609 Element* source_canvas_element = | 607 Element* source_canvas_element = |
| 610 GetDocument().createElement("canvas", exception_state); | 608 GetDocument().createElement("canvas", exception_state); |
| 611 EXPECT_FALSE(exception_state.HadException()); | 609 EXPECT_FALSE(exception_state.HadException()); |
| 612 HTMLCanvasElement* source_canvas = | 610 HTMLCanvasElement* source_canvas = |
| 613 static_cast<HTMLCanvasElement*>(source_canvas_element); | 611 static_cast<HTMLCanvasElement*>(source_canvas_element); |
| 614 IntSize source_size( | 612 IntSize source_size( |
| 615 10, | 613 10, 10 * CanvasHeuristicParameters::kExpensiveImageSizeRatio + 1); |
| 616 10 * ExpensiveCanvasHeuristicParameters::kExpensiveImageSizeRatio + 1); | |
| 617 std::unique_ptr<UnacceleratedImageBufferSurface> source_surface = | 614 std::unique_ptr<UnacceleratedImageBufferSurface> source_surface = |
| 618 WTF::MakeUnique<UnacceleratedImageBufferSurface>(source_size, kNonOpaque); | 615 WTF::MakeUnique<UnacceleratedImageBufferSurface>(source_size, kNonOpaque); |
| 619 source_canvas->CreateImageBufferUsingSurfaceForTesting( | 616 source_canvas->CreateImageBufferUsingSurfaceForTesting( |
| 620 std::move(source_surface)); | 617 std::move(source_surface)); |
| 621 | 618 |
| 622 const ImageBitmapOptions default_options; | 619 const ImageBitmapOptions default_options; |
| 623 Optional<IntRect> crop_rect = IntRect(IntPoint(0, 0), source_size); | 620 Optional<IntRect> crop_rect = IntRect(IntPoint(0, 0), source_size); |
| 624 // Go through an ImageBitmap to avoid triggering a display list fallback | 621 // Go through an ImageBitmap to avoid triggering a display list fallback |
| 625 ImageBitmap* source_image_bitmap = | 622 ImageBitmap* source_image_bitmap = |
| 626 ImageBitmap::Create(source_canvas, crop_rect, default_options); | 623 ImageBitmap::Create(source_canvas, crop_rect, default_options); |
| 627 | 624 |
| 628 Context2d()->drawImage(GetScriptState(), source_image_bitmap, 0, 0, 1, 1, 0, | 625 Context2d()->drawImage(GetScriptState(), source_image_bitmap, 0, 0, 1, 1, 0, |
| 629 0, 1, 1, exception_state); | 626 0, 1, 1, exception_state); |
| 630 EXPECT_FALSE(exception_state.HadException()); | 627 EXPECT_FALSE(exception_state.HadException()); |
| 631 | 628 |
| 632 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); | 629 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); |
| 633 EXPECT_TRUE(surface_ptr->IsRecording()); | 630 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 634 } | 631 } |
| 635 | 632 |
| 636 TEST_F(CanvasRenderingContext2DTest, | 633 TEST_F(CanvasRenderingContext2DTest, |
| 637 NoLayerPromotionUnderExpensivePathPointCount) { | 634 NoLayerPromotionUnderExpensivePathPointCount) { |
| 638 CreateContext(kNonOpaque); | 635 CreateContext(kNonOpaque); |
| 639 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 636 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 640 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 637 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 641 auto* surface_ptr = surface.get(); | 638 auto* surface_ptr = surface.get(); |
| 642 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 639 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 643 | 640 |
| 644 Context2d()->beginPath(); | 641 Context2d()->beginPath(); |
| 645 Context2d()->moveTo(7, 5); | 642 Context2d()->moveTo(7, 5); |
| 646 for (int i = 1; | 643 for (int i = 1; i < CanvasHeuristicParameters::kExpensivePathPointCount - 1; |
| 647 i < ExpensiveCanvasHeuristicParameters::kExpensivePathPointCount - 1; | |
| 648 i++) { | 644 i++) { |
| 649 float angle_rad = | 645 float angle_rad = twoPiFloat * i / |
| 650 twoPiFloat * i / | 646 (CanvasHeuristicParameters::kExpensivePathPointCount - 1); |
| 651 (ExpensiveCanvasHeuristicParameters::kExpensivePathPointCount - 1); | |
| 652 Context2d()->lineTo(5 + 2 * cos(angle_rad), 5 + 2 * sin(angle_rad)); | 647 Context2d()->lineTo(5 + 2 * cos(angle_rad), 5 + 2 * sin(angle_rad)); |
| 653 } | 648 } |
| 654 Context2d()->fill(); | 649 Context2d()->fill(); |
| 655 | 650 |
| 656 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); | 651 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); |
| 657 EXPECT_TRUE(surface_ptr->IsRecording()); | 652 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 658 } | 653 } |
| 659 | 654 |
| 660 TEST_F(CanvasRenderingContext2DTest, | 655 TEST_F(CanvasRenderingContext2DTest, |
| 661 LayerPromotionOverExpensivePathPointCount) { | 656 LayerPromotionOverExpensivePathPointCount) { |
| 662 CreateContext(kNonOpaque); | 657 CreateContext(kNonOpaque); |
| 663 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 658 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 664 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 659 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 665 auto* surface_ptr = surface.get(); | 660 auto* surface_ptr = surface.get(); |
| 666 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 661 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 667 | 662 |
| 668 Context2d()->beginPath(); | 663 Context2d()->beginPath(); |
| 669 Context2d()->moveTo(7, 5); | 664 Context2d()->moveTo(7, 5); |
| 670 for (int i = 1; | 665 for (int i = 1; i < CanvasHeuristicParameters::kExpensivePathPointCount + 1; |
| 671 i < ExpensiveCanvasHeuristicParameters::kExpensivePathPointCount + 1; | |
| 672 i++) { | 666 i++) { |
| 673 float angle_rad = | 667 float angle_rad = twoPiFloat * i / |
| 674 twoPiFloat * i / | 668 (CanvasHeuristicParameters::kExpensivePathPointCount + 1); |
| 675 (ExpensiveCanvasHeuristicParameters::kExpensivePathPointCount + 1); | |
| 676 Context2d()->lineTo(5 + 2 * cos(angle_rad), 5 + 2 * sin(angle_rad)); | 669 Context2d()->lineTo(5 + 2 * cos(angle_rad), 5 + 2 * sin(angle_rad)); |
| 677 } | 670 } |
| 678 Context2d()->fill(); | 671 Context2d()->fill(); |
| 679 | 672 |
| 680 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); | 673 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); |
| 681 EXPECT_TRUE(surface_ptr->IsRecording()); | 674 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 682 } | 675 } |
| 683 | 676 |
| 684 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWhenPathIsConcave) { | 677 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWhenPathIsConcave) { |
| 685 CreateContext(kNonOpaque); | 678 CreateContext(kNonOpaque); |
| 686 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 679 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 687 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 680 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 688 auto* surface_ptr = surface.get(); | 681 auto* surface_ptr = surface.get(); |
| 689 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 682 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 690 | 683 |
| 691 Context2d()->beginPath(); | 684 Context2d()->beginPath(); |
| 692 Context2d()->moveTo(1, 1); | 685 Context2d()->moveTo(1, 1); |
| 693 Context2d()->lineTo(5, 5); | 686 Context2d()->lineTo(5, 5); |
| 694 Context2d()->lineTo(9, 1); | 687 Context2d()->lineTo(9, 1); |
| 695 Context2d()->lineTo(5, 9); | 688 Context2d()->lineTo(5, 9); |
| 696 Context2d()->fill(); | 689 Context2d()->fill(); |
| 697 | 690 |
| 698 if (ExpensiveCanvasHeuristicParameters::kConcavePathsAreExpensive) { | 691 if (CanvasHeuristicParameters::kConcavePathsAreExpensive) { |
| 699 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); | 692 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); |
| 700 } else { | 693 } else { |
| 701 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); | 694 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); |
| 702 } | 695 } |
| 703 EXPECT_TRUE(surface_ptr->IsRecording()); | 696 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 704 } | 697 } |
| 705 | 698 |
| 706 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionWithRectangleClip) { | 699 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionWithRectangleClip) { |
| 707 CreateContext(kNonOpaque); | 700 CreateContext(kNonOpaque); |
| 708 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 701 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 727 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 720 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 728 | 721 |
| 729 Context2d()->beginPath(); | 722 Context2d()->beginPath(); |
| 730 Context2d()->moveTo(1, 1); | 723 Context2d()->moveTo(1, 1); |
| 731 Context2d()->lineTo(5, 5); | 724 Context2d()->lineTo(5, 5); |
| 732 Context2d()->lineTo(9, 1); | 725 Context2d()->lineTo(9, 1); |
| 733 Context2d()->lineTo(5, 9); | 726 Context2d()->lineTo(5, 9); |
| 734 Context2d()->clip(); | 727 Context2d()->clip(); |
| 735 Context2d()->fillRect(0, 0, 4, 4); | 728 Context2d()->fillRect(0, 0, 4, 4); |
| 736 | 729 |
| 737 if (ExpensiveCanvasHeuristicParameters::kComplexClipsAreExpensive) { | 730 if (CanvasHeuristicParameters::kComplexClipsAreExpensive) { |
| 738 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); | 731 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); |
| 739 } else { | 732 } else { |
| 740 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); | 733 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); |
| 741 } | 734 } |
| 742 EXPECT_TRUE(surface_ptr->IsRecording()); | 735 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 743 } | 736 } |
| 744 | 737 |
| 745 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWithBlurredShadow) { | 738 TEST_F(CanvasRenderingContext2DTest, LayerPromotionWithBlurredShadow) { |
| 746 CreateContext(kNonOpaque); | 739 CreateContext(kNonOpaque); |
| 747 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 740 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 748 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 741 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 749 auto* surface_ptr = surface.get(); | 742 auto* surface_ptr = surface.get(); |
| 750 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 743 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 751 | 744 |
| 752 Context2d()->setShadowColor(String("red")); | 745 Context2d()->setShadowColor(String("red")); |
| 753 Context2d()->setShadowBlur(1.0f); | 746 Context2d()->setShadowBlur(1.0f); |
| 754 Context2d()->fillRect(1, 1, 1, 1); | 747 Context2d()->fillRect(1, 1, 1, 1); |
| 755 | 748 |
| 756 if (ExpensiveCanvasHeuristicParameters::kBlurredShadowsAreExpensive) { | 749 if (CanvasHeuristicParameters::kBlurredShadowsAreExpensive) { |
| 757 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); | 750 EXPECT_TRUE(CanvasElement().ShouldBeDirectComposited()); |
| 758 } else { | 751 } else { |
| 759 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); | 752 EXPECT_FALSE(CanvasElement().ShouldBeDirectComposited()); |
| 760 } | 753 } |
| 761 EXPECT_TRUE(surface_ptr->IsRecording()); | 754 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 762 } | 755 } |
| 763 | 756 |
| 764 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionWithSharpShadow) { | 757 TEST_F(CanvasRenderingContext2DTest, NoLayerPromotionWithSharpShadow) { |
| 765 CreateContext(kNonOpaque); | 758 CreateContext(kNonOpaque); |
| 766 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 759 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 778 | 771 |
| 779 TEST_F(CanvasRenderingContext2DTest, NoFallbackWithSmallState) { | 772 TEST_F(CanvasRenderingContext2DTest, NoFallbackWithSmallState) { |
| 780 CreateContext(kNonOpaque); | 773 CreateContext(kNonOpaque); |
| 781 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 774 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 782 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 775 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 783 auto* surface_ptr = surface.get(); | 776 auto* surface_ptr = surface.get(); |
| 784 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 777 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 785 | 778 |
| 786 Context2d()->fillRect(0, 0, 1, 1); // To have a non-empty dirty rect. | 779 Context2d()->fillRect(0, 0, 1, 1); // To have a non-empty dirty rect. |
| 787 for (int i = 0; | 780 for (int i = 0; |
| 788 i < | 781 i < CanvasHeuristicParameters::kExpensiveRecordingStackDepth - 1; ++i) { |
| 789 ExpensiveCanvasHeuristicParameters::kExpensiveRecordingStackDepth - 1; | |
| 790 ++i) { | |
| 791 Context2d()->save(); | 782 Context2d()->save(); |
| 792 Context2d()->translate(1.0f, 0.0f); | 783 Context2d()->translate(1.0f, 0.0f); |
| 793 } | 784 } |
| 794 CanvasElement().FinalizeFrame(); // To close the current frame. | 785 CanvasElement().FinalizeFrame(); // To close the current frame. |
| 795 | 786 |
| 796 EXPECT_TRUE(surface_ptr->IsRecording()); | 787 EXPECT_TRUE(surface_ptr->IsRecording()); |
| 797 } | 788 } |
| 798 | 789 |
| 799 TEST_F(CanvasRenderingContext2DTest, FallbackWithLargeState) { | 790 TEST_F(CanvasRenderingContext2DTest, FallbackWithLargeState) { |
| 800 CreateContext(kNonOpaque); | 791 CreateContext(kNonOpaque); |
| 801 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( | 792 auto surface = WTF::MakeUnique<RecordingImageBufferSurface>( |
| 802 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); | 793 IntSize(10, 10), RecordingImageBufferSurface::kAllowFallback, kNonOpaque); |
| 803 auto* surface_ptr = surface.get(); | 794 auto* surface_ptr = surface.get(); |
| 804 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 795 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 805 | 796 |
| 806 Context2d()->fillRect(0, 0, 1, 1); // To have a non-empty dirty rect. | 797 Context2d()->fillRect(0, 0, 1, 1); // To have a non-empty dirty rect. |
| 807 for (int i = 0; | 798 for (int i = 0; i < CanvasHeuristicParameters::kExpensiveRecordingStackDepth; |
| 808 i < ExpensiveCanvasHeuristicParameters::kExpensiveRecordingStackDepth; | |
| 809 ++i) { | 799 ++i) { |
| 810 Context2d()->save(); | 800 Context2d()->save(); |
| 811 Context2d()->translate(1.0f, 0.0f); | 801 Context2d()->translate(1.0f, 0.0f); |
| 812 } | 802 } |
| 813 CanvasElement().FinalizeFrame(); // To close the current frame. | 803 CanvasElement().FinalizeFrame(); // To close the current frame. |
| 814 | 804 |
| 815 EXPECT_FALSE(surface_ptr->IsRecording()); | 805 EXPECT_FALSE(surface_ptr->IsRecording()); |
| 816 } | 806 } |
| 817 | 807 |
| 818 TEST_F(CanvasRenderingContext2DTest, OpaqueDisplayListFallsBackForText) { | 808 TEST_F(CanvasRenderingContext2DTest, OpaqueDisplayListFallsBackForText) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 std::unique_ptr<Canvas2DImageBufferSurface> surface( | 937 std::unique_ptr<Canvas2DImageBufferSurface> surface( |
| 948 new Canvas2DImageBufferSurface(bridge, size)); | 938 new Canvas2DImageBufferSurface(bridge, size)); |
| 949 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); | 939 CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(surface)); |
| 950 | 940 |
| 951 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); | 941 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); |
| 952 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); | 942 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); |
| 953 EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); | 943 EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); |
| 954 | 944 |
| 955 DummyExceptionStateForTesting exception_state; | 945 DummyExceptionStateForTesting exception_state; |
| 956 for (int i = 0; | 946 for (int i = 0; |
| 957 i < | 947 i < CanvasHeuristicParameters::kGPUReadbackMinSuccessiveFrames - 1; |
| 958 ExpensiveCanvasHeuristicParameters::kGPUReadbackMinSuccessiveFrames - 1; | |
| 959 i++) { | 948 i++) { |
| 960 Context2d()->getImageData(0, 0, 1, 1, exception_state); | 949 Context2d()->getImageData(0, 0, 1, 1, exception_state); |
| 961 CanvasElement().FinalizeFrame(); | 950 CanvasElement().FinalizeFrame(); |
| 962 | 951 |
| 963 EXPECT_FALSE(exception_state.HadException()); | 952 EXPECT_FALSE(exception_state.HadException()); |
| 964 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); | 953 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); |
| 965 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); | 954 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); |
| 966 EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); | 955 EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); |
| 967 } | 956 } |
| 968 | 957 |
| 969 Context2d()->getImageData(0, 0, 1, 1, exception_state); | 958 Context2d()->getImageData(0, 0, 1, 1, exception_state); |
| 970 CanvasElement().FinalizeFrame(); | 959 CanvasElement().FinalizeFrame(); |
| 971 | 960 |
| 972 EXPECT_FALSE(exception_state.HadException()); | 961 EXPECT_FALSE(exception_state.HadException()); |
| 973 if (ExpensiveCanvasHeuristicParameters::kGPUReadbackForcesNoAcceleration) { | 962 if (CanvasHeuristicParameters::kGPUReadbackForcesNoAcceleration) { |
| 974 EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); | 963 EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); |
| 975 EXPECT_EQ(0u, GetGlobalAcceleratedImageBufferCount()); | 964 EXPECT_EQ(0u, GetGlobalAcceleratedImageBufferCount()); |
| 976 EXPECT_EQ(0, GetGlobalGPUMemoryUsage()); | 965 EXPECT_EQ(0, GetGlobalGPUMemoryUsage()); |
| 977 } else { | 966 } else { |
| 978 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); | 967 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); |
| 979 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); | 968 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); |
| 980 EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); | 969 EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); |
| 981 } | 970 } |
| 982 | 971 |
| 983 // Restore global state to prevent side-effects on other tests | 972 // Restore global state to prevent side-effects on other tests |
| 984 RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled( | 973 RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled( |
| 985 saved_fixed_rendering_mode); | 974 saved_fixed_rendering_mode); |
| 986 } | 975 } |
| 987 | 976 |
| 988 TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) { | 977 TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) { |
| 989 bool saved_fixed_rendering_mode = | 978 bool saved_fixed_rendering_mode = |
| 990 RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled(); | 979 RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled(); |
| 991 RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(false); | 980 RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(false); |
| 992 | 981 |
| 993 enum TestVariants { | 982 enum TestVariants { |
| 994 kLargeTextureDisablesAcceleration = 0, | 983 kLargeTextureDisablesAcceleration = 0, |
| 995 kSmallTextureDoesNotDisableAcceleration = 1, | 984 kSmallTextureDoesNotDisableAcceleration = 1, |
| 996 | 985 |
| 997 kTestVariantCount = 2, | 986 kTestVariantCount = 2, |
| 998 }; | 987 }; |
| 999 | 988 |
| 1000 for (int test_variant = 0; test_variant < kTestVariantCount; test_variant++) { | 989 for (int test_variant = 0; test_variant < kTestVariantCount; test_variant++) { |
| 1001 int delta = test_variant == kLargeTextureDisablesAcceleration ? 1 : -1; | 990 int delta = test_variant == kLargeTextureDisablesAcceleration ? 1 : -1; |
| 1002 int src_size = std::sqrt(static_cast<float>( | 991 int src_size = |
| 1003 ExpensiveCanvasHeuristicParameters:: | 992 std::sqrt(static_cast<float>( |
| 1004 kDrawImageTextureUploadSoftSizeLimit)) + | 993 CanvasHeuristicParameters::kDrawImageTextureUploadSoftSizeLimit)) + |
| 1005 delta; | 994 delta; |
| 1006 int dst_size = | 995 int dst_size = |
| 1007 src_size / | 996 src_size / |
| 1008 std::sqrt(static_cast<float>( | 997 std::sqrt(static_cast<float>( |
| 1009 ExpensiveCanvasHeuristicParameters:: | 998 CanvasHeuristicParameters:: |
| 1010 kDrawImageTextureUploadSoftSizeLimitScaleThreshold)) - | 999 kDrawImageTextureUploadSoftSizeLimitScaleThreshold)) - |
| 1011 delta; | 1000 delta; |
| 1012 | 1001 |
| 1013 CreateContext(kNonOpaque); | 1002 CreateContext(kNonOpaque); |
| 1014 FakeGLES2Interface gl; | 1003 FakeGLES2Interface gl; |
| 1015 std::unique_ptr<FakeWebGraphicsContext3DProvider> context_provider( | 1004 std::unique_ptr<FakeWebGraphicsContext3DProvider> context_provider( |
| 1016 new FakeWebGraphicsContext3DProvider(&gl)); | 1005 new FakeWebGraphicsContext3DProvider(&gl)); |
| 1017 IntSize size(dst_size, dst_size); | 1006 IntSize size(dst_size, dst_size); |
| 1018 RefPtr<Canvas2DLayerBridge> bridge = | 1007 RefPtr<Canvas2DLayerBridge> bridge = |
| 1019 MakeBridge(std::move(context_provider), size, | 1008 MakeBridge(std::move(context_provider), size, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1045 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); | 1034 EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); |
| 1046 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); | 1035 EXPECT_EQ(1u, GetGlobalAcceleratedImageBufferCount()); |
| 1047 EXPECT_EQ(8 * dst_size * dst_size, GetGlobalGPUMemoryUsage()); | 1036 EXPECT_EQ(8 * dst_size * dst_size, GetGlobalGPUMemoryUsage()); |
| 1048 } | 1037 } |
| 1049 } | 1038 } |
| 1050 // Restore global state to prevent side-effects on other tests | 1039 // Restore global state to prevent side-effects on other tests |
| 1051 RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled( | 1040 RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled( |
| 1052 saved_fixed_rendering_mode); | 1041 saved_fixed_rendering_mode); |
| 1053 } | 1042 } |
| 1054 | 1043 |
| 1055 TEST_F(CanvasRenderingContext2DTest, | |
| 1056 IsAccelerationOptimalForCanvasContentHeuristic) { | |
| 1057 CreateContext(kNonOpaque); | |
| 1058 | |
| 1059 auto fake_accelerate_surface = | |
| 1060 WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 10), | |
| 1061 kNonOpaque); | |
| 1062 CanvasElement().CreateImageBufferUsingSurfaceForTesting( | |
| 1063 std::move(fake_accelerate_surface)); | |
| 1064 | |
| 1065 NonThrowableExceptionState exception_state; | |
| 1066 | |
| 1067 CanvasRenderingContext2D* context = Context2d(); | |
| 1068 EXPECT_TRUE(context->IsAccelerationOptimalForCanvasContent()); | |
| 1069 | |
| 1070 context->fillRect(10, 10, 100, 100); | |
| 1071 EXPECT_TRUE(context->IsAccelerationOptimalForCanvasContent()); | |
| 1072 | |
| 1073 int num_reps = 100; | |
| 1074 for (int i = 0; i < num_reps; i++) { | |
| 1075 context->fillText("Text", 10, 10, 1); // faster with no acceleration | |
| 1076 } | |
| 1077 EXPECT_FALSE(context->IsAccelerationOptimalForCanvasContent()); | |
| 1078 | |
| 1079 for (int i = 0; i < num_reps; i++) { | |
| 1080 context->fillRect(10, 10, 200, 200); // faster with acceleration | |
| 1081 } | |
| 1082 EXPECT_TRUE(context->IsAccelerationOptimalForCanvasContent()); | |
| 1083 | |
| 1084 for (int i = 0; i < num_reps * 100; i++) { | |
| 1085 context->strokeText("Text", 10, 10, 1); // faster with no acceleration | |
| 1086 } | |
| 1087 EXPECT_FALSE(context->IsAccelerationOptimalForCanvasContent()); | |
| 1088 } | |
| 1089 | |
| 1090 TEST_F(CanvasRenderingContext2DTest, DisableAcceleration) { | 1044 TEST_F(CanvasRenderingContext2DTest, DisableAcceleration) { |
| 1091 CreateContext(kNonOpaque); | 1045 CreateContext(kNonOpaque); |
| 1092 | 1046 |
| 1093 auto fake_accelerate_surface = | 1047 auto fake_accelerate_surface = |
| 1094 WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 10), | 1048 WTF::MakeUnique<FakeAcceleratedImageBufferSurface>(IntSize(10, 10), |
| 1095 kNonOpaque); | 1049 kNonOpaque); |
| 1096 CanvasElement().CreateImageBufferUsingSurfaceForTesting( | 1050 CanvasElement().CreateImageBufferUsingSurfaceForTesting( |
| 1097 std::move(fake_accelerate_surface)); | 1051 std::move(fake_accelerate_surface)); |
| 1098 CanvasRenderingContext2D* context = Context2d(); | 1052 CanvasRenderingContext2D* context = Context2d(); |
| 1099 | 1053 |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1685 | 1639 |
| 1686 // Wake up again, which should request a compositing update synchronously. | 1640 // Wake up again, which should request a compositing update synchronously. |
| 1687 GetDocument().GetPage()->SetVisibilityState(kPageVisibilityStateVisible, | 1641 GetDocument().GetPage()->SetVisibilityState(kPageVisibilityStateVisible, |
| 1688 false); | 1642 false); |
| 1689 EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED, | 1643 EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED, |
| 1690 layer->NeedsCompositingInputsUpdate()); | 1644 layer->NeedsCompositingInputsUpdate()); |
| 1691 RunUntilIdle(); // Clear task queue. | 1645 RunUntilIdle(); // Clear task queue. |
| 1692 } | 1646 } |
| 1693 | 1647 |
| 1694 } // namespace blink | 1648 } // namespace blink |
| OLD | NEW |