diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-16 09:59:13 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-20 10:28:53 +0000 |
commit | 6c11fb357ec39bf087b8b632e2b1e375aef1b38b (patch) | |
tree | c8315530db18a8ee566521c39ab8a6af4f72bc03 /chromium/components/viz/service/display/overlay_unittest.cc | |
parent | 3ffaed019d0772e59d6cdb2d0d32fe4834c31f72 (diff) | |
download | qtwebengine-chromium-6c11fb357ec39bf087b8b632e2b1e375aef1b38b.tar.gz |
BASELINE: Update Chromium to 74.0.3729.159
Change-Id: I8d2497da544c275415aedd94dd25328d555de811
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/viz/service/display/overlay_unittest.cc')
-rw-r--r-- | chromium/components/viz/service/display/overlay_unittest.cc | 499 |
1 files changed, 331 insertions, 168 deletions
diff --git a/chromium/components/viz/service/display/overlay_unittest.cc b/chromium/components/viz/service/display/overlay_unittest.cc index 8a7cc7c2f3b..dd71b44894b 100644 --- a/chromium/components/viz/service/display/overlay_unittest.cc +++ b/chromium/components/viz/service/display/overlay_unittest.cc @@ -7,8 +7,10 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/containers/flat_map.h" #include "base/test/scoped_feature_list.h" +#include "base/unguessable_token.h" #include "cc/test/fake_output_surface_client.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/resource_provider_test_utils.h" @@ -18,6 +20,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/stream_video_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" +#include "components/viz/common/quads/video_hole_draw_quad.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/service/display/ca_layer_overlay.h" #include "components/viz/service/display/display_resource_provider.h" @@ -34,6 +37,7 @@ #include "components/viz/test/test_context_provider.h" #include "components/viz/test/test_gles2_interface.h" #include "components/viz/test/test_shared_bitmap_manager.h" +#include "gpu/config/gpu_finch_features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -204,12 +208,6 @@ class OverlayOutputSurface : public OutputSurface { bool has_alpha, bool use_stencil) override {} void SwapBuffers(OutputSurfaceFrame frame) override {} -#if BUILDFLAG(ENABLE_VULKAN) - gpu::VulkanSurface* GetVulkanSurface() override { - NOTREACHED(); - return nullptr; - } -#endif uint32_t GetFramebufferCopyTextureFormat() override { // TestContextProvider has no real framebuffer, just use RGB. return GL_RGB; @@ -253,6 +251,7 @@ std::unique_ptr<RenderPass> CreateRenderPass() { SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState(); shared_state->opacity = 1.f; + shared_state->has_surface_damage = true; return pass; } @@ -368,6 +367,19 @@ TextureDrawQuad* CreateCandidateQuadAt( shared_quad_state, render_pass, rect, ui::ProtectedVideoType::kClear); } +// For Cast we use VideoHoleDrawQuad, and that's what overlay_processor_ +// expects. +VideoHoleDrawQuad* CreateVideoHoleDrawQuadAt( + const SharedQuadState* shared_quad_state, + RenderPass* render_pass, + const gfx::Rect& rect) { + base::UnguessableToken overlay_plane_id = base::UnguessableToken::Create(); + auto* overlay_quad = + render_pass->CreateAndAppendDrawQuad<VideoHoleDrawQuad>(); + overlay_quad->SetNew(shared_quad_state, rect, rect, overlay_plane_id); + return overlay_quad; +} + TextureDrawQuad* CreateTransparentCandidateQuadAt( DisplayResourceProvider* parent_resource_provider, ClientResourceProvider* child_resource_provider, @@ -397,29 +409,6 @@ TextureDrawQuad* CreateTransparentCandidateQuadAt( return overlay_quad; } -StreamVideoDrawQuad* CreateCandidateVideoQuadAt( - DisplayResourceProvider* parent_resource_provider, - ClientResourceProvider* child_resource_provider, - ContextProvider* child_context_provider, - const SharedQuadState* shared_quad_state, - RenderPass* render_pass, - const gfx::Rect& rect, - const gfx::Transform& transform) { - bool needs_blending = false; - gfx::Size resource_size_in_pixels = rect.size(); - bool is_overlay_candidate = true; - ResourceId resource_id = CreateResource( - parent_resource_provider, child_resource_provider, child_context_provider, - resource_size_in_pixels, is_overlay_candidate); - - auto* overlay_quad = - render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>(); - overlay_quad->SetNew(shared_quad_state, rect, rect, needs_blending, - resource_id, resource_size_in_pixels, transform); - - return overlay_quad; -} - TextureDrawQuad* CreateFullscreenCandidateQuad( DisplayResourceProvider* parent_resource_provider, ClientResourceProvider* child_resource_provider, @@ -431,18 +420,6 @@ TextureDrawQuad* CreateFullscreenCandidateQuad( shared_quad_state, render_pass, render_pass->output_rect); } -StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad( - DisplayResourceProvider* parent_resource_provider, - ClientResourceProvider* child_resource_provider, - ContextProvider* child_context_provider, - const SharedQuadState* shared_quad_state, - RenderPass* render_pass, - const gfx::Transform& transform) { - return CreateCandidateVideoQuadAt( - parent_resource_provider, child_resource_provider, child_context_provider, - shared_quad_state, render_pass, render_pass->output_rect, transform); -} - YUVVideoDrawQuad* CreateFullscreenCandidateYUVVideoQuad( DisplayResourceProvider* parent_resource_provider, ClientResourceProvider* child_resource_provider, @@ -1057,7 +1034,46 @@ TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) { TextureDrawQuad* quad = CreateFullscreenCandidateQuad( resource_provider_.get(), child_resource_provider_.get(), child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + quad->background_color = SK_ColorRED; + + OverlayCandidateList candidate_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &candidate_list, + nullptr, nullptr, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, candidate_list.size()); +} + +TEST_F(SingleOverlayOnTopTest, AcceptBlackBackgroundColor) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + TextureDrawQuad* quad = CreateFullscreenCandidateQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + quad->background_color = SK_ColorBLACK; + + OverlayCandidateList candidate_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &candidate_list, + nullptr, nullptr, &damage_rect_, &content_bounds_); + EXPECT_EQ(1U, candidate_list.size()); +} + +TEST_F(SingleOverlayOnTopTest, RejectBlackBackgroundColorWithBlending) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + TextureDrawQuad* quad = CreateFullscreenCandidateQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); quad->background_color = SK_ColorBLACK; + quad->needs_blending = true; OverlayCandidateList candidate_list; OverlayProcessor::FilterOperationsMap render_pass_filters; @@ -1545,101 +1561,6 @@ TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) { EXPECT_EQ(0U, candidate_list.size()); } -TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateVideoQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kSwapTransform); - - OverlayCandidateList candidate_list; - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_backdrop_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - EXPECT_EQ(0U, candidate_list.size()); -} - -TEST_F(UnderlayTest, AllowVideoXMirrorTransform) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateVideoQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kXMirrorTransform); - - OverlayCandidateList candidate_list; - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_backdrop_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - EXPECT_EQ(1U, candidate_list.size()); -} - -TEST_F(UnderlayTest, AllowVideoBothMirrorTransform) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateVideoQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kBothMirrorTransform); - - OverlayCandidateList candidate_list; - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_backdrop_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - EXPECT_EQ(1U, candidate_list.size()); -} - -TEST_F(UnderlayTest, AllowVideoNormalTransform) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateVideoQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kNormalTransform); - - OverlayCandidateList candidate_list; - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_backdrop_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - EXPECT_EQ(1U, candidate_list.size()); -} - -TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateVideoQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kYMirrorTransform); - - OverlayCandidateList candidate_list; - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_backdrop_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - EXPECT_EQ(1U, candidate_list.size()); -} - TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) { output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); @@ -2022,6 +1943,46 @@ TEST_F(UnderlayTest, UpdateDamageRectWhenNoPromotion) { } } +// Tests that no damage occurs due to unchanged elements on top of HW underlays +TEST_F(UnderlayTest, DamageSubtractedWhenElementsOnHwUnderlayNotChanged) { + for (int i = 0; i < 2; ++i) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + + gfx::Rect rect(2, 3); + SharedQuadState* non_damaged_quad_state = + pass->shared_quad_state_list.AllocateAndCopyFrom( + pass->shared_quad_state_list.back()); + // Element on top has not changed (no damage caused by this quad) + non_damaged_quad_state->has_surface_damage = false; + CreateSolidColorQuadAt(non_damaged_quad_state, SK_ColorBLACK, pass.get(), + rect); + + CreateFullscreenCandidateQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.front(), + pass.get()); + + damage_rect_ = kOverlayRect; + + OverlayCandidateList candidate_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &candidate_list, + nullptr, nullptr, &damage_rect_, &content_bounds_); + + // The damage rect should not be subtracted on the first frame + if (i == 0) + EXPECT_FALSE(damage_rect_.IsEmpty()); + } + // As the UI on top of the underlay persists and does not change, damage + // should be subtracted. + EXPECT_TRUE(damage_rect_.IsEmpty()); +} + TEST_F(UnderlayCastTest, NoOverlayContentBounds) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -2043,10 +2004,8 @@ TEST_F(UnderlayCastTest, NoOverlayContentBounds) { TEST_F(UnderlayCastTest, FullScreenOverlayContentBounds) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kOverlayRect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + kOverlayRect); OverlayCandidateList candidate_list; OverlayProcessor::FilterOperationsMap render_pass_filters; @@ -2070,10 +2029,8 @@ TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) { const gfx::Rect kTopRight(128, 0, 128, 128); std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kOverlayBottomRightRect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + kOverlayBottomRightRect); CreateOpaqueQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), kLeftSide, SK_ColorBLACK); @@ -2100,10 +2057,8 @@ TEST_F(UnderlayCastTest, OverlayOccludedContentBounds) { CreateOpaqueQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), kOverlayTopLeftRect); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kOverlayRect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + kOverlayRect); OverlayCandidateList candidate_list; OverlayProcessor::FilterOperationsMap render_pass_filters; @@ -2127,10 +2082,8 @@ TEST_F(UnderlayCastTest, OverlayOccludedUnionContentBounds) { CreateOpaqueQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), kOverlayBottomRightRect); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kOverlayRect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + kOverlayRect); OverlayCandidateList candidate_list; OverlayProcessor::FilterOperationsMap render_pass_filters; @@ -2157,10 +2110,8 @@ TEST_F(UnderlayCastTest, RoundOverlayContentBounds) { transform.Translate(0.5f, 0.5f); std::unique_ptr<RenderPass> pass = CreateRenderPassWithTransform(transform); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - overlay_rect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + overlay_rect); CreateOpaqueQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), gfx::Rect(0, 0, 10, 10), SK_ColorWHITE); @@ -2191,10 +2142,8 @@ TEST_F(UnderlayCastTest, RoundContentBounds) { transform.Translate(0.5f, 0.5f); std::unique_ptr<RenderPass> pass = CreateRenderPassWithTransform(transform); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - overlay_rect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + overlay_rect); CreateOpaqueQuadAt(resource_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), gfx::Rect(0, 0, 255, 255), SK_ColorWHITE); @@ -2220,10 +2169,8 @@ TEST_F(UnderlayCastTest, PrimaryPlaneOverlayIsTransparentWithUnderlay) { pass->shared_quad_state_list.back(), pass.get(), output_rect, SK_ColorWHITE); - CreateCandidateQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kOverlayRect, ui::ProtectedVideoType::kHardwareProtected); + CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(), + kOverlayRect); OverlayCandidateList candidate_list; OverlayCandidate candidate; @@ -2504,7 +2451,8 @@ TEST_F(DCLayerOverlayTest, Occluded) { EXPECT_EQ(0U, overlay_list.size()); EXPECT_EQ(2U, dc_layer_list.size()); EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); - EXPECT_EQ(-1, dc_layer_list.back().z_order); + EXPECT_EQ(-1, dc_layer_list.front().z_order); + EXPECT_EQ(-2, dc_layer_list.back().z_order); // Entire underlay rect must be redrawn. EXPECT_EQ(gfx::Rect(0, 0, 256, 256), damage_rect_); } @@ -2539,11 +2487,174 @@ TEST_F(DCLayerOverlayTest, Occluded) { EXPECT_EQ(0U, overlay_list.size()); EXPECT_EQ(2U, dc_layer_list.size()); EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); - EXPECT_EQ(-1, dc_layer_list.back().z_order); + EXPECT_EQ(-1, dc_layer_list.front().z_order); + EXPECT_EQ(-2, dc_layer_list.back().z_order); // The underlay rectangle is the same, so the damage for first video quad is // contained within the combined occluding rects for this and the last // frame. Second video quad also adds its damage. - EXPECT_EQ(gfx::Rect(1, 2, 255, 254), damage_rect_); + + // This is calculated by carving out the underlay rect size from the + // damage_rect, adding back the quads on top and then the overlay/underlay + // rects from the previous frame. The damage rect carried over from the + // revious frame with multiple overlays cannot be skipped. + EXPECT_EQ(gfx::Rect(0, 0, 256, 256), damage_rect_); + } +} + +TEST_F(DCLayerOverlayTest, DamageRectWithoutVideoDamage) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays); + { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + // Occluding quad fully contained in video rect. + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(0, 3, 100, 100), SK_ColorWHITE); + // Non-occluding quad fully outside video rect + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(210, 210, 20, 20), SK_ColorWHITE); + // Underlay video quad + auto* video_quad = CreateFullscreenCandidateYUVVideoQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + video_quad->rect = gfx::Rect(0, 0, 200, 200); + video_quad->visible_rect = video_quad->rect; + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + // Damage rect fully outside video quad + damage_rect_ = gfx::Rect(210, 210, 20, 20); + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &overlay_list, + nullptr, &dc_layer_list, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().z_order); + // All rects must be redrawn at the first frame. + EXPECT_EQ(gfx::Rect(0, 0, 230, 230), damage_rect_); + } + { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + // Occluding quad fully contained in video rect. + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(0, 3, 100, 100), SK_ColorWHITE); + // Non-occluding quad fully outside video rect + CreateOpaqueQuadAt(resource_provider_.get(), + pass->shared_quad_state_list.back(), pass.get(), + gfx::Rect(210, 210, 20, 20), SK_ColorWHITE); + // Underlay video quad + auto* video_quad = CreateFullscreenCandidateYUVVideoQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + video_quad->rect = gfx::Rect(0, 0, 200, 200); + video_quad->visible_rect = video_quad->rect; + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + // Damage rect fully outside video quad + damage_rect_ = gfx::Rect(210, 210, 20, 20); + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &overlay_list, + nullptr, &dc_layer_list, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().z_order); + // Only the non-overlay damaged rect need to be drawn by the gl compositor + EXPECT_EQ(gfx::Rect(210, 210, 20, 20), damage_rect_); + } +} + +TEST_F(DCLayerOverlayTest, DamageRectWithNonRootOverlay) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures({features::kDirectCompositionUnderlays, + features::kDirectCompositionNonrootOverlays}, + {}); + { + // A root solid quad + std::unique_ptr<RenderPass> root_pass = CreateRenderPass(); + CreateOpaqueQuadAt( + resource_provider_.get(), root_pass->shared_quad_state_list.back(), + root_pass.get(), gfx::Rect(210, 0, 20, 20), SK_ColorWHITE); + + // A non-root video quad + std::unique_ptr<RenderPass> nonroot_pass = CreateRenderPass(); + auto* video_quad = CreateFullscreenCandidateYUVVideoQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), nonroot_pass->shared_quad_state_list.back(), + nonroot_pass.get()); + video_quad->rect = gfx::Rect(0, 0, 200, 200); + video_quad->visible_rect = video_quad->rect; + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + // Damage rect fully outside video quad + damage_rect_ = gfx::Rect(210, 0, 20, 20); + RenderPassList pass_list; + pass_list.push_back(std::move(nonroot_pass)); + pass_list.push_back(std::move(root_pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &overlay_list, + nullptr, &dc_layer_list, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().z_order); + // damage_rect returned from ProcessForOverlays() is for root render pass + // only. Non-root damage rect is not included. + EXPECT_EQ(gfx::Rect(210, 0, 20, 20), damage_rect_); + } + { + // A root solid quad + std::unique_ptr<RenderPass> root_pass = CreateRenderPass(); + CreateOpaqueQuadAt( + resource_provider_.get(), root_pass->shared_quad_state_list.back(), + root_pass.get(), gfx::Rect(210, 0, 20, 20), SK_ColorWHITE); + + // A non-root video quad + std::unique_ptr<RenderPass> nonroot_pass = CreateRenderPass(); + auto* video_quad = CreateFullscreenCandidateYUVVideoQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), nonroot_pass->shared_quad_state_list.back(), + nonroot_pass.get()); + video_quad->rect = gfx::Rect(0, 0, 200, 200); + video_quad->visible_rect = video_quad->rect; + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + // Damage rect fully outside video quad + damage_rect_ = gfx::Rect(210, 0, 20, 20); + RenderPassList pass_list; + pass_list.push_back(std::move(nonroot_pass)); + pass_list.push_back(std::move(root_pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &overlay_list, + nullptr, &dc_layer_list, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().z_order); + // Nonroot damage_rect from the previous frame should be added to this frame + EXPECT_EQ(gfx::Rect(0, 0, 230, 200), damage_rect_); } } @@ -2672,8 +2783,10 @@ TEST_F(DCLayerOverlayTest, MultiplePassDamageRect) { EXPECT_EQ(gfx::Rect(0, 0, 256, 256), pass_list[0]->damage_rect); EXPECT_EQ(gfx::Rect(), pass_list[1]->damage_rect); EXPECT_EQ(gfx::Rect(0, 100, 256, 156), root_damage_rect); + // Overlay damage handling is done entirely within DCOverlayProcessor so this + // is expected to return an empty rect gfx::Rect overlay_damage = overlay_processor_->GetAndResetOverlayDamage(); - EXPECT_EQ(gfx::Rect(0, 100, 256, 256), overlay_damage); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), overlay_damage); EXPECT_EQ(1u, pass_list[0]->quad_list.size()); EXPECT_EQ(DrawQuad::SOLID_COLOR, @@ -2801,6 +2914,56 @@ TEST_F(DCLayerOverlayTest, TransparentOnTop) { } } +TEST_F(DCLayerOverlayTest, UnderlayDamageRectWithQuadOnTopUnchanged) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays); + + for (int i = 0; i < 3; i++) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + // Add a solid color quad on top + SharedQuadState* shared_state_on_top = pass->shared_quad_state_list.back(); + CreateSolidColorQuadAt(shared_state_on_top, SK_ColorRED, pass.get(), + kOverlayBottomRightRect); + + SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState(); + shared_state->opacity = 1.f; + CreateFullscreenCandidateYUVVideoQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), shared_state, pass.get()); + + DCLayerOverlayList dc_layer_list; + OverlayCandidateList overlay_list; + OverlayProcessor::FilterOperationsMap render_pass_filters; + OverlayProcessor::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + gfx::Rect damage_rect_ = kOverlayRect; + + // The quad on top does not give damage on the third frame + if (i == 2) + shared_state_on_top->has_surface_damage = false; + else + shared_state_on_top->has_surface_damage = true; + + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, &overlay_list, + nullptr, &dc_layer_list, &damage_rect_, &content_bounds_); + EXPECT_EQ(0U, overlay_list.size()); + EXPECT_EQ(1U, dc_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); + EXPECT_EQ(-1, dc_layer_list.back().z_order); + // Damage rect should be unchanged on initial frame, but should be reduced + // to the size of quad on top, and empty on the third frame. + if (i == 0) + EXPECT_EQ(kOverlayRect, damage_rect_); + else if (i == 1) + EXPECT_EQ(kOverlayBottomRightRect, damage_rect_); + else if (i == 2) + EXPECT_EQ(gfx::Rect(), damage_rect_); + } +} + class OverlayInfoRendererGL : public GLRenderer { public: OverlayInfoRendererGL(const RendererSettings* settings, |