#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include <stddef.h>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/time/time_override.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/resource_provider_test_utils.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/buildflags.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_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/resource_id.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/service/display/display_resource_provider_skia.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/overlay_candidate_factory.h"
#include "components/viz/service/display/overlay_candidate_temporal_tracker.h"
#include "components/viz/service/display/overlay_processor_using_strategy.h"
#include "components/viz/service/display/overlay_proposed_candidate.h"
#include "components/viz/service/display/overlay_strategy_fullscreen.h"
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include "components/viz/test/fake_skia_output_surface.h"
#include "components/viz/test/test_context_provider.h"
#include "components/viz/test/test_gles2_interface.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/linear_gradient.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/test/geometry_util.h"
#include "ui/latency/latency_info.h"
#if BUILDFLAG(IS_OZONE)
#include "components/viz/service/display/overlay_processor_delegated.h"
#include "ui/base/ui_base_features.h"
#endif
#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "components/viz/service/display/ca_layer_overlay.h"
#endif
_;
Mock;
namespace viz {
namespace {
RoundedDisplayMasksInfo;
const gfx::Size kDisplaySize(256, 256);
const gfx::Rect kOverlayRect(0, 0, 256, 256);
const gfx::Rect kOverlayTopLeftRect(0, 0, 128, 128);
const gfx::Rect kOverlayTopRightRect(128, 0, 128, 128);
const gfx::Rect kOverlayBottomRightRect(128, 128, 128, 128);
const gfx::Rect kOverlayClipRect(0, 0, 128, 128);
const gfx::PointF kUVTopLeft(0.1f, 0.2f);
const gfx::PointF kUVBottomRight(1.0f, 1.0f);
const SharedImageFormat kDefaultSIFormat = …;
const OverlayCandidateFactory::OverlayContext kTestOverlayContext;
class TimeTicksOverride { … };
base::TimeTicks TimeTicksOverride::now_ticks_ = …;
class TestOverlayProcessor : public OverlayProcessorUsingStrategy { … };
class FullscreenOverlayProcessor : public TestOverlayProcessor { … };
float GetMinScaleFactor(const OverlayCandidate& candidate) { … }
class DefaultOverlayProcessor : public TestOverlayProcessor { … };
class SingleOverlayProcessor : public DefaultOverlayProcessor { … };
class MultiOverlayProcessorBase : public TestOverlayProcessor { … };
class MultiOverlayProcessor : public MultiOverlayProcessorBase { … };
class MultiSingleOnTopProcessor : public MultiOverlayProcessorBase { … };
class SizeSortedMultiSingleOnTopProcessor : public MultiOverlayProcessorBase { … };
class MultiUnderlayProcessor : public MultiOverlayProcessorBase { … };
class SizeSortedMultiOverlayProcessorBase : public MultiOverlayProcessorBase { … };
class SizeSortedMultiOverlayProcessor
: public SizeSortedMultiOverlayProcessorBase { … };
class SizeSortedMultiUnderlayProcessor
: public SizeSortedMultiOverlayProcessorBase { … };
class TypeAndSizeSortedMultiOverlayProcessor
: public MultiOverlayProcessorBase { … };
class AllowCandidateWithMasksSortedMultiOverlayProcessor
: public MultiOverlayProcessorBase { … };
class SingleOnTopOverlayProcessor : public DefaultOverlayProcessor { … };
class UnderlayOverlayProcessor : public DefaultOverlayProcessor { … };
class TransitionOverlayProcessor : public DefaultOverlayProcessor { … };
class TransparentUnderlayOverlayProcessor : public DefaultOverlayProcessor { … };
#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
class UnderlayCastOverlayProcessor : public DefaultOverlayProcessor {
public:
UnderlayCastOverlayProcessor() : DefaultOverlayProcessor() {
strategies_.push_back(std::make_unique<OverlayStrategyUnderlayCast>(this));
}
};
#endif
class ChangeThresholdOnTopOverlayProcessor : public DefaultOverlayProcessor { … };
class FullThresholdUnderlayOverlayProcessor : public DefaultOverlayProcessor { … };
std::unique_ptr<AggregatedRenderPass> CreateRenderPass() { … }
static ResourceId CreateResourceInLayerTree(
ClientResourceProvider* child_resource_provider,
const gfx::Size& size,
bool is_overlay_candidate,
SharedImageFormat format) { … }
ResourceId CreateResource(DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const gfx::Size& size,
bool is_overlay_candidate,
SharedImageFormat format,
SurfaceId test_surface_id = SurfaceId()) { … }
ResourceId CreateResource(DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const gfx::Size& size,
bool is_overlay_candidate) { … }
SolidColorDrawQuad* CreateSolidColorQuadAt(
const SharedQuadState* shared_quad_state,
SkColor4f color,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect) { … }
TextureDrawQuad* CreateCandidateQuadAt(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect,
gfx::ProtectedVideoType protected_video_type,
SharedImageFormat format,
const gfx::Size& resource_size_in_pixels,
SurfaceId test_surface_id = SurfaceId()) { … }
TextureDrawQuad* CreateCandidateQuadAt(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect,
gfx::ProtectedVideoType protected_video_type,
SharedImageFormat format,
SurfaceId test_surface_id = SurfaceId()) { … }
TextureDrawQuad* CreateCandidateQuadAt(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect,
SurfaceId test_surface_id = SurfaceId()) { … }
#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
std::unique_ptr<AggregatedRenderPass> CreateRenderPassWithTransform(
const gfx::Transform& transform) {
AggregatedRenderPassId render_pass_id{1};
gfx::Rect output_rect(0, 0, 256, 256);
auto pass = std::make_unique<AggregatedRenderPass>();
pass->SetNew(render_pass_id, output_rect, output_rect, gfx::Transform());
SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->opacity = 1.f;
shared_state->quad_to_target_transform = transform;
return pass;
}
VideoHoleDrawQuad* CreateVideoHoleDrawQuadAt(
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* 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;
}
#endif
TextureDrawQuad* CreateTransparentCandidateQuadAt(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect) { … }
TextureDrawQuad* CreateFullscreenCandidateQuad(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass) { … }
TextureDrawQuad* CreateQuadWithRoundedDisplayMasksAt(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
bool is_overlay_candidate,
const gfx::Rect& rect,
const RoundedDisplayMasksInfo& rounded_display_masks_info) { … }
TextureDrawQuad* CreateFullscreenQuadWithRoundedDisplayMasks(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
bool is_overlay_candidate,
const RoundedDisplayMasksInfo& rounded_display_masks_info) { … }
void CreateOpaqueQuadAt(DisplayResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect) { … }
void CreateOpaqueQuadAt(DisplayResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect,
SkColor4f color) { … }
void CreateFullscreenOpaqueQuad(DisplayResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass) { … }
static void CompareRenderPassLists(
const AggregatedRenderPassList& expected_list,
const AggregatedRenderPassList& actual_list) { … }
SkM44 GetIdentityColorMatrix() { … }
SkM44 GetNonIdentityColorMatrix() { … }
template <typename OverlayProcessorType>
class OverlayTest : public testing::Test { … };
template <typename OverlayProcessorType>
class UseMultipleOverlaysTest : public OverlayTest<OverlayProcessorType> { … };
FullscreenOverlayTest;
SingleOverlayOnTopTest;
ChangeSingleOnTopTest;
FullThresholdTest;
TransitionOverlayTypeTest;
UnderlayTest;
TransparentUnderlayTest;
#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
using UnderlayCastTest = OverlayTest<UnderlayCastOverlayProcessor>;
#endif
MultiOverlayTest;
MultiUnderlayTest;
MultiSingleOnTopOverlayTest;
SizeSortedMultiSingeOnTopOverlayTest;
SizeSortedMultiUnderlayOverlayTest;
SizeSortedMultiOverlayTest;
TypeAndSizeSortedMultiOverlayTest;
AllowCandidateWithMasksSortedMultiOverlayTest;
TEST(OverlayTest, OverlaysProcessorHasStrategy) { … }
#if !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_WIN)
TEST_F(FullscreenOverlayTest, DRMDefaultBlackOptimization) { … }
TEST_F(FullscreenOverlayTest,
DRMDefaultBlackOptimizationWithRoundedDisplayMaskTextures) { … }
TEST_F(FullscreenOverlayTest, SuccessfulOverlay) { … }
TEST_F(FullscreenOverlayTest, FailIfFullscreenQuadHasRoundedDisplayMasks) { … }
TEST_F(FullscreenOverlayTest, FailOnOutputColorMatrix) { … }
TEST_F(FullscreenOverlayTest, AlphaFail) { … }
TEST_F(FullscreenOverlayTest, SuccessfulResourceSizeInPixels) { … }
TEST_F(FullscreenOverlayTest, OnTopFail) { … }
TEST_F(FullscreenOverlayTest, NotCoveringFullscreenFail) { … }
TEST_F(FullscreenOverlayTest, RemoveFullscreenQuadFromQuadList) { … }
TEST_F(SingleOverlayOnTopTest, SuccessfulOverlay) { … }
TEST_F(MultiSingleOnTopOverlayTest,
SuccessfulOverlay_OccludedByOverlayRoundedDisplayMaskCandidate) { … }
TEST_F(MultiSingleOnTopOverlayTest, RoundedDisplayMaskCandidateNotDrawnOnTop) { … }
DeathMultiSingleOnTopOverlayTest;
TEST_F(DeathMultiSingleOnTopOverlayTest,
RoundedDisplayMaskCandidatesOverlapsEachOther) { … }
TEST_F(DeathMultiSingleOnTopOverlayTest,
RoundedDisplayMaskCandidateIsNotOverlayCandidate) { … }
TEST_F(MultiSingleOnTopOverlayTest,
PromoteRoundedDisplayMaskCandidateIfOccludeOtherCandidates) { … }
TEST_F(
MultiSingleOnTopOverlayTest,
FailToPromoteRoundedDisplayMaskCandidatesIfTheyDontOccludeOtherCandidates) { … }
TEST_F(MultiSingleOnTopOverlayTest,
OcclusionOptimizationForRoundedDisplayMaskCandidate) { … }
TEST_F(SingleOverlayOnTopTest, PrioritizeBiggerOne) { … }
TEST_F(SingleOverlayOnTopTest, CandidateIdCollision) { … }
TEST_F(SingleOverlayOnTopTest, CandidateTrackIdUniqueSurface) { … }
TEST_F(SingleOverlayOnTopTest, StablePrioritizeIntervalFrame) { … }
TEST_F(SingleOverlayOnTopTest, OpaqueOverlayDamageSubtract) { … }
TEST_F(SingleOverlayOnTopTest, NonOpaquePureOverlayFirstFrameDamage) { … }
TEST_F(SingleOverlayOnTopTest, NonOpaquePureOverlayNonOccludingDamage) { … }
TEST_F(SingleOverlayOnTopTest, DamageRect) { … }
TEST_F(SingleOverlayOnTopTest, DamageWithMutipleSurfaceDamage) { … }
TEST_F(SingleOverlayOnTopTest, NoCandidates) { … }
TEST_F(SingleOverlayOnTopTest, OccludedCandidates) { … }
TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) { … }
TEST_F(SingleOverlayOnTopTest, AcceptBlending) { … }
TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) { … }
TEST_F(SingleOverlayOnTopTest, AcceptBlackBackgroundColor) { … }
TEST_F(UnderlayTest, AcceptBlackBackgroundColorWithRoundedCorners) { … }
TEST_F(UnderlayTest, RejectBlackBackgroundColorWithGradient) { … }
TEST_F(SingleOverlayOnTopTest, RejectBlackBackgroundColorWithBlending) { … }
TEST_F(SingleOverlayOnTopTest, RejectBlendMode) { … }
TEST_F(SingleOverlayOnTopTest, RejectOpacity) { … }
TEST_F(SingleOverlayOnTopTest, RejectNearestNeighbor) { … }
TEST_F(SingleOverlayOnTopTest, RejectNonAxisAlignedTransform) { … }
TEST_F(SingleOverlayOnTopTest, AllowClipped) { … }
TEST_F(UnderlayTest, ReplacementQuad) { … }
TEST_F(UnderlayTest, AllowVerticalFlip) { … }
TEST_F(UnderlayTest, AllowHorizontalFlip) { … }
TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) { … }
TEST_F(SingleOverlayOnTopTest, AcceptMirrorYTransform) { … }
TEST_F(UnderlayTest, Allow90DegreeRotation) { … }
TEST_F(UnderlayTest, Allow180DegreeRotation) { … }
TEST_F(UnderlayTest, Allow270DegreeRotation) { … }
TEST_F(UnderlayTest, AllowsOpaqueCandidates) { … }
TEST_F(UnderlayTest, DisallowsQuadsWithRoundedDisplayMasks) { … }
TEST_F(UnderlayTest, DisallowsTransparentCandidates) { … }
TEST_F(UnderlayTest, DisallowFilteredQuadOnTop) { … }
TEST_F(UnderlayTest, AllowFilteredQuadOnTopForProtectedVideo) { … }
TEST_F(TransparentUnderlayTest, AllowsOpaqueCandidates) { … }
TEST_F(TransparentUnderlayTest, AllowsTransparentCandidates) { … }
TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) { … }
TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) { … }
TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) { … }
TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) { … }
TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) { … }
TEST_F(SingleOverlayOnTopTest, CheckPromotionHintBasic) { … }
TEST_F(ChangeSingleOnTopTest, DoNotPromoteIfContentsDontChange) { … }
TEST_F(FullThresholdTest, ThresholdTestForPrioritization) { … }
TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) { … }
TEST_F(UnderlayTest, AllowOnTop) { … }
TEST_F(TransitionOverlayTypeTest, DamageChangeOnTransistionOverlayType) { … }
TEST_F(TransitionOverlayTypeTest, DamageWhenOverlayBecomesTransparent) { … }
TEST_F(TransitionOverlayTypeTest, MaskFilterBringsUnderlay) { … }
TEST_F(UnderlayTest, InitialUnderlayDamageNotExcluded) { … }
TEST_F(UnderlayTest, DamageExcludedForConsecutiveIdenticalUnderlays) { … }
TEST_F(UnderlayTest, DamageNotExcludedForNonIdenticalConsecutiveUnderlays) { … }
TEST_F(UnderlayTest, DamageNotExcludedForNonConsecutiveIdenticalUnderlays) { … }
TEST_F(
UnderlayTest,
DamageNotExcludedForConsecutiveUnderlaysIfOneHasMaskFilterAndOtherDoesNot) { … }
TEST_F(UnderlayTest, DamageExcludedForCandidateAndThoseOccluded) { … }
TEST_F(UnderlayTest, DamageExtractedWhenQuadsAboveDontOverlap) { … }
TEST_F(UnderlayTest, PrimaryPlaneOverlayIsTransparentWithUnderlay) { … }
TEST_F(UnderlayTest, UpdateDamageWhenChangingUnderlays) { … }
TEST_F(UnderlayTest, OverlayCandidateTemporalTracker) { … }
TEST_F(UnderlayTest, UpdateDamageRectWhenNoPromotion) { … }
TEST_F(UnderlayTest, CandidateNoDamageWhenQuadSharedStateNoOccludingDamage) { … }
#endif
#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
TEST_F(UnderlayCastTest, ReplacementQuad) {
auto pass = CreateRenderPass();
CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
kOverlayRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
ASSERT_EQ(1U, pass_list.size());
ASSERT_EQ(1U, pass_list.front()->quad_list.size());
EXPECT_EQ(SkColors::kTransparent, static_cast<SolidColorDrawQuad*>(
pass_list.front()->quad_list.front())
->color);
EXPECT_FALSE(pass_list.front()->quad_list.front()->ShouldDrawWithBlending());
EXPECT_FALSE(pass_list.front()
->quad_list.front()
->shared_quad_state->are_contents_opaque);
}
TEST_F(UnderlayCastTest, NoOverlayContentBounds) {
auto pass = CreateRenderPass();
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(0U, content_bounds_.size());
}
TEST_F(UnderlayCastTest, FullScreenOverlayContentBounds) {
auto pass = CreateRenderPass();
CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
kOverlayRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_TRUE(content_bounds_[0].IsEmpty());
}
TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) {
AddExpectedRectToOverlayProcessor(gfx::RectF(kOverlayBottomRightRect));
const gfx::Rect kLeftSide(0, 0, 128, 256);
const gfx::Rect kTopRight(128, 0, 128, 128);
auto pass = CreateRenderPass();
CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
kOverlayBottomRightRect);
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), kLeftSide,
SkColors::kBlack);
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), kTopRight,
SkColors::kBlack);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_TRUE(content_bounds_[0].IsEmpty());
}
TEST_F(UnderlayCastTest, OverlayOccludedContentBounds) {
auto pass = CreateRenderPass();
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
kOverlayRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(kOverlayTopLeftRect, content_bounds_[0]);
}
TEST_F(UnderlayCastTest, OverlayOccludedUnionContentBounds) {
auto pass = CreateRenderPass();
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayBottomRightRect);
CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
kOverlayRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(kOverlayRect, content_bounds_[0]);
}
TEST_F(UnderlayCastTest, RoundOverlayContentBounds) {
const gfx::Rect overlay_rect(1, 1, 8, 8);
AddExpectedRectToOverlayProcessor(gfx::RectF(1.5f, 1.5f, 8, 8));
gfx::Transform transform;
transform.Translate(0.5f, 0.5f);
auto pass = CreateRenderPassWithTransform(transform);
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), SkColors::kWhite);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(gfx::Rect(0, 0, 11, 11), content_bounds_[0]);
}
TEST_F(UnderlayCastTest, RoundContentBounds) {
gfx::Rect overlay_rect = kOverlayRect;
overlay_rect.Inset(gfx::Insets::TLBR(0, 0, 1, 1));
AddExpectedRectToOverlayProcessor(gfx::RectF(0.5f, 0.5f, 255, 255));
gfx::Transform transform;
transform.Translate(0.5f, 0.5f);
auto pass = CreateRenderPassWithTransform(transform);
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), SkColors::kWhite);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
EXPECT_EQ(1U, content_bounds_.size());
EXPECT_EQ(kOverlayRect, content_bounds_[0]);
}
TEST_F(UnderlayCastTest, NoOverlayPromotionWithoutProtectedContent) {
auto pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
ASSERT_TRUE(candidate_list.empty());
EXPECT_TRUE(content_bounds_.empty());
}
TEST_F(UnderlayCastTest, OverlayPromotionWithMaskFilter) {
auto pass = CreateRenderPass();
SurfaceDamageRectList surface_damage_rect_list;
auto* sqs = pass->shared_quad_state_list.front();
sqs->overlay_damage_index = 0;
surface_damage_rect_list.emplace_back(damage_rect_);
sqs->mask_filter_info =
gfx::MaskFilterInfo(gfx::RectF(kOverlayRect), gfx::RoundedCornersF(1.f),
gfx::LinearGradient::GetEmpty());
CreateVideoHoleDrawQuadAt(sqs, pass.get(), kOverlayRect);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList 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,
std::move(surface_damage_rect_list), nullptr, &candidate_list,
&damage_rect_, &content_bounds_);
ASSERT_EQ(1U, content_bounds_.size());
EXPECT_TRUE(content_bounds_.front().IsEmpty());
ASSERT_EQ(1U, pass_list.size());
ASSERT_EQ(1U, pass_list.front()->quad_list.size());
EXPECT_EQ(SkColors::kBlack, static_cast<SolidColorDrawQuad*>(
pass_list.front()->quad_list.front())
->color);
EXPECT_FALSE(pass_list.front()
->quad_list.front()
->shared_quad_state->are_contents_opaque);
EXPECT_EQ(
SkBlendMode::kDstOut,
pass_list.front()->quad_list.front()->shared_quad_state->blend_mode);
}
#endif
#if BUILDFLAG(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
TEST_F(UnderlayCastTest, PrimaryPlaneOverlayIsAlwaysTransparent) {
auto pass = CreateRenderPass();
gfx::Rect output_rect = pass->output_rect;
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
output_rect, SkColors::kWhite);
OverlayCandidateList candidate_list;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
AggregatedRenderPassList pass_list;
pass_list.push_back(std::move(pass));
auto output_surface_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay(
kDisplaySize, kDisplaySize, kDefaultSIFormat, gfx::ColorSpace(),
false , 1.0f , gpu::Mailbox());
SurfaceDamageRectList surface_damage_rect_list;
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_backdrop_filters,
std::move(surface_damage_rect_list), &output_surface_plane,
&candidate_list, &damage_rect_, &content_bounds_);
ASSERT_EQ(true, output_surface_plane.enable_blending);
EXPECT_EQ(0U, content_bounds_.size());
}
#endif
#if BUILDFLAG(IS_APPLE)
class CALayerOverlayRPDQTest : public CALayerOverlayTest {
protected:
void SetUp() override {
CALayerOverlayTest::SetUp();
pass_list_.push_back(CreateRenderPass());
pass_ = pass_list_.back().get();
quad_ = pass_->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
render_pass_id_ = 3;
}
void ProcessForOverlays() {
overlay_processor_->ProcessForOverlays(
resource_provider_.get(), &pass_list_, GetIdentityColorMatrix(),
render_pass_filters_, render_pass_backdrop_filters_,
std::move(surface_damage_rect_list_), nullity, &ca_layer_list_,
&damage_rect_, &content_bounds_);
}
AggregatedRenderPassList pass_list_;
AggregatedRenderPass* pass_;
AggregatedRenderPassDrawQuad* quad_;
int render_pass_id_;
cc::FilterOperations filters_;
cc::FilterOperations backdrop_filters_;
OverlayProcessorInterface::FilterOperationsMap render_pass_filters_;
OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters_;
CALayerOverlayList ca_layer_list_;
SurfaceDamageRectList surface_damage_rect_list_;
};
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadNoFilters) {
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(1U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadAllValidFilters) {
filters_.Append(cc::FilterOperation::CreateGrayscaleFilter(0.1f));
filters_.Append(cc::FilterOperation::CreateSepiaFilter(0.2f));
filters_.Append(cc::FilterOperation::CreateSaturateFilter(0.3f));
filters_.Append(cc::FilterOperation::CreateHueRotateFilter(0.4f));
filters_.Append(cc::FilterOperation::CreateInvertFilter(0.5f));
filters_.Append(cc::FilterOperation::CreateBrightnessFilter(0.6f));
filters_.Append(cc::FilterOperation::CreateContrastFilter(0.7f));
filters_.Append(cc::FilterOperation::CreateOpacityFilter(0.8f));
filters_.Append(cc::FilterOperation::CreateBlurFilter(0.9f));
filters_.Append(cc::FilterOperation::CreateDropShadowFilter(
gfx::Point(10, 20), 1.0f, SK_ColorGREEN));
render_pass_filters_[render_pass_id_] = &filters_;
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(1U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadOpacityFilterScale) {
filters_.Append(cc::FilterOperation::CreateOpacityFilter(0.8f));
render_pass_filters_[render_pass_id_] = &filters_;
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(1U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadBlurFilterScale) {
filters_.Append(cc::FilterOperation::CreateBlurFilter(0.8f));
render_pass_filters_[render_pass_id_] = &filters_;
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(1U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest,
AggregatedRenderPassDrawQuadDropShadowFilterScale) {
filters_.Append(cc::FilterOperation::CreateDropShadowFilter(
gfx::Point(10, 20), 1.0f, SK_ColorGREEN));
render_pass_filters_[render_pass_id_] = &filters_;
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 2), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(1U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadBackgroundFilter) {
backdrop_filters_.Append(cc::FilterOperation::CreateGrayscaleFilter(0.1f));
render_pass_backdrop_filters_[render_pass_id_] = &backdrop_filters_;
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(0U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadMask) {
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, ResourceId(2), gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(1U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, AggregatedRenderPassDrawQuadUnsupportedFilter) {
filters_.Append(cc::FilterOperation::CreateZoomFilter(0.9f, 1));
render_pass_filters_[render_pass_id_] = &filters_;
quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, kInvalidResourceId, gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(),
false, 1.0f);
ProcessForOverlays();
EXPECT_EQ(0U, ca_layer_list_.size());
}
TEST_F(CALayerOverlayRPDQTest, TooManyRenderPassDrawQuads) {
filters_.Append(cc::FilterOperation::CreateBlurFilter(0.8f));
int count = 35;
for (int i = 0; i < count; ++i) {
auto* quad = pass_->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
quad->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect,
kOverlayRect, render_pass_id_, ResourceId(2), gfx::RectF(),
gfx::Size(), gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(),
false, 1.0f);
}
ProcessForOverlays();
EXPECT_EQ(0U, ca_layer_list_.size());
}
#endif
void AddQuad(gfx::Rect quad_rect,
const gfx::Transform& quad_to_target_transform,
AggregatedRenderPass* render_pass) { … }
TEST_F(SingleOverlayOnTopTest, IsOverlayRequiredBasic) { … }
TEST_F(SingleOverlayOnTopTest, IsOverlayRequiredHwProtectedVideo) { … }
TEST_F(SingleOverlayOnTopTest, RequiredOverlayClippingAndSubsampling) { … }
TEST_F(SingleOverlayOnTopTest,
RequiredOverlayClippingAndSubsamplingWithPrimary) { … }
TEST_F(UnderlayTest, EstimateOccludedDamage) { … }
TEST_F(UnderlayTest, ProtectedVideoOverlayScaling) { … }
#if BUILDFLAG(IS_OZONE)
TileDrawQuad* CreateTileCandidateQuadAt(
DisplayResourceProvider* parent_resource_provider,
ClientResourceProvider* child_resource_provider,
RasterContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
AggregatedRenderPass* render_pass,
const gfx::Rect& rect) { … }
class TestDelegatedOverlayProcessor : public OverlayProcessorDelegated { … };
class DelegatedTest : public OverlayTest<TestDelegatedOverlayProcessor> { … };
gfx::Transform MakePerspectiveTransform() { … }
gfx::Transform MakeShearTransform() { … }
gfx::Transform MakeRotationTransform() { … }
TEST_F(DelegatedTest, ForwardMultipleBasic) { … }
TEST_F(DelegatedTest, ForwardBackgroundColor) { … }
TEST_F(DelegatedTest, DoNotDelegateCopyRequest) { … }
TEST_F(DelegatedTest, BlockDelegationWithNonRootCopies) { … }
TEST_F(DelegatedTest, TestClipHandCrafted) { … }
TEST_F(DelegatedTest, TestVisibleRectClip) { … }
TEST_F(DelegatedTest, TestClipComputed) { … }
TEST_F(DelegatedTest, TestClipAggregateRenderPass) { … }
TEST_F(DelegatedTest, TestClipWithPrimary) { … }
TEST_F(DelegatedTest, ScaledBufferDamage) { … }
TEST_F(DelegatedTest, QuadTypes) { … }
TEST_F(DelegatedTest, NonAxisAlignedCandidateStatus) { … }
class DelegatedTestNonDelegated : public DelegatedTest { … };
TEST_F(DelegatedTestNonDelegated, TextureQuadNearest) { … }
TEST_F(DelegatedTestNonDelegated, TileQuadNearest) { … }
#endif
TEST_F(MultiUnderlayTest, DamageWhenDemotingTwoUnderlays) { … }
TEST_F(MultiUnderlayTest, DamageWhenDemotingOneUnderlay) { … }
TEST_F(MultiOverlayTest, DamageOnlyForNewUnderlays) { … }
TEST_F(MultiOverlayTest, DamageMaskFilterChange) { … }
TEST_F(MultiOverlayTest, DamageOccluded) { … }
TEST_F(MultiOverlayTest, FullscreenOnly) { … }
TEST_F(MultiOverlayTest, RequiredOverlayOnly) { … }
TEST_F(MultiOverlayTest, CappedAtMaxOverlays) { … }
TEST_F(MultiOverlayTest, RoundedDisplayMaskCandidateFailsToPromote) { … }
TEST_F(MultiOverlayTest,
DontPromoteCandidatesWithMasksIfAreOnlyOverlayCandidatesNotRejected) { … }
TEST_F(AllowCandidateWithMasksSortedMultiOverlayTest,
DontPromoteCandidatesWithMasksIfAreOnlySingleOnTopCandidates) { … }
TEST_F(TypeAndSizeSortedMultiOverlayTest,
PrioritizationWithRoundedDisplayMasks) { … }
TEST_F(TransitionOverlayTypeTest, FullscreenFavored) { … }
TEST_F(SizeSortedMultiOverlayTest, OverlaysAreSorted) { … }
TEST_F(SizeSortedMultiUnderlayOverlayTest, UnderlaysAreSorted) { … }
class MultiUnderlayPromotedTest : public MultiUnderlayTest,
public testing::WithParamInterface<bool> { … };
TEST_P(MultiUnderlayPromotedTest, UnderlaysBlendPrimaryPlane) { … }
INSTANTIATE_TEST_SUITE_P(…);
}
}