blob: 1f4f678667ea385dbd0adcad33b20001026450c4 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/slim/surface_layer.h"
#include <algorithm>
#include <utility>
#include "cc/slim/layer_tree_impl.h"
#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/surface_range.h"
namespace cc::slim {
// static
scoped_refptr<SurfaceLayer> SurfaceLayer::Create() {
return base::AdoptRef(new SurfaceLayer());
}
SurfaceLayer::SurfaceLayer() = default;
SurfaceLayer::~SurfaceLayer() = default;
void SurfaceLayer::SetSurfaceId(const viz::SurfaceId& surface_id,
const cc::DeadlinePolicy& deadline_policy) {
if (surface_range_.end() == surface_id &&
deadline_policy.use_existing_deadline()) {
return;
}
SetSurfaceRange(viz::SurfaceRange(surface_range_.start(), surface_id));
if (!surface_range_.IsValid()) {
deadline_in_frames_ = 0u;
} else if (!deadline_policy.use_existing_deadline()) {
deadline_in_frames_ = deadline_policy.deadline_in_frames();
}
}
void SurfaceLayer::SetStretchContentToFillBounds(
bool stretch_content_to_fill_bounds) {
if (stretch_content_to_fill_bounds_ == stretch_content_to_fill_bounds) {
return;
}
stretch_content_to_fill_bounds_ = stretch_content_to_fill_bounds;
NotifyPropertyChanged();
}
void SurfaceLayer::SetOldestAcceptableFallback(
const viz::SurfaceId& surface_id) {
// The fallback should never move backwards.
DCHECK(!surface_range_.start() ||
!surface_range_.start()->IsNewerThan(surface_id));
if (surface_range_.start() == surface_id) {
return;
}
SetSurfaceRange(viz::SurfaceRange(
surface_id.is_valid() ? std::optional<viz::SurfaceId>(surface_id)
: std::nullopt,
surface_range_.end()));
}
void SurfaceLayer::SetLayerTree(LayerTree* tree) {
if (layer_tree() == tree) {
return;
}
if (layer_tree() && surface_range_.IsValid()) {
static_cast<LayerTreeImpl*>(layer_tree())
->RemoveSurfaceRange(surface_range_);
}
Layer::SetLayerTree(tree);
if (layer_tree() && surface_range_.IsValid()) {
static_cast<LayerTreeImpl*>(layer_tree())->AddSurfaceRange(surface_range_);
}
}
void SurfaceLayer::SetSurfaceRange(const viz::SurfaceRange& surface_range) {
if (surface_range_ == surface_range) {
return;
}
if (layer_tree() && surface_range_.IsValid()) {
static_cast<LayerTreeImpl*>(layer_tree())
->RemoveSurfaceRange(surface_range_);
}
surface_range_ = surface_range;
if (layer_tree() && surface_range_.IsValid()) {
static_cast<LayerTreeImpl*>(layer_tree())->AddSurfaceRange(surface_range_);
}
NotifyPropertyChanged();
}
void SurfaceLayer::AppendQuads(viz::CompositorRenderPass& render_pass,
FrameData& data,
const gfx::Transform& transform_to_root,
const gfx::Transform& transform_to_target,
const gfx::Rect* clip_in_target,
const gfx::Rect& visible_rect,
float opacity) {
viz::SharedQuadState* quad_state =
CreateAndAppendSharedQuadState(render_pass, data, transform_to_target,
clip_in_target, visible_rect, opacity);
if (surface_range_.IsValid()) {
auto* quad = render_pass.CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
quad->SetNew(quad_state, quad_state->quad_layer_rect,
quad_state->visible_quad_layer_rect, surface_range_,
background_color(), stretch_content_to_fill_bounds_);
data.activation_dependencies.insert(surface_range_.end());
if (deadline_in_frames_) {
if (!data.deadline_in_frames) {
data.deadline_in_frames = 0u;
}
data.deadline_in_frames =
std::max(*data.deadline_in_frames, *deadline_in_frames_);
} else {
data.use_default_lower_bound_deadline = true;
}
auto& hit_test_region = data.hit_test_regions->emplace_back();
hit_test_region.flags = viz::HitTestRegionFlags::kHitTestMouse |
viz::HitTestRegionFlags::kHitTestTouch |
viz::HitTestRegionFlags::kHitTestChildSurface;
hit_test_region.frame_sink_id = surface_range_.end().frame_sink_id();
hit_test_region.rect = quad_state->visible_quad_layer_rect;
// False will set transform to identity.
bool rv = transform_to_root.GetInverse(&hit_test_region.transform);
if (!rv || !hit_test_region.transform.Preserves2dAxisAlignment()) {
hit_test_region.flags |= viz::HitTestRegionFlags::kHitTestAsk;
hit_test_region.async_hit_test_reasons |=
viz::AsyncHitTestReasons::kIrregularClip;
}
} else {
auto* quad = render_pass.CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
quad->SetNew(quad_state, quad_state->quad_layer_rect,
quad_state->visible_quad_layer_rect, background_color(),
false /* force_anti_aliasing_off */);
}
// Unless the client explicitly calls SetSurfaceId again after this
// commit, don't block on |surface_range_| again.
deadline_in_frames_ = 0u;
}
} // namespace cc::slim