#include "cc/layers/view_transition_content_layer_impl.h"
#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "cc/base/math_util.h"
#include "cc/layers/append_quads_context.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/layer_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "components/viz/common/quads/shared_element_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/view_transition_element_resource_id.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
namespace cc {
std::unique_ptr<ViewTransitionContentLayerImpl>
ViewTransitionContentLayerImpl::Create(
LayerTreeImpl* tree_impl,
int id,
const viz::ViewTransitionElementResourceId& resource_id,
bool is_live_content_layer,
const gfx::RectF& max_extents_rect) {
return base::WrapUnique(new ViewTransitionContentLayerImpl(
tree_impl, id, resource_id, is_live_content_layer, max_extents_rect));
}
ViewTransitionContentLayerImpl::ViewTransitionContentLayerImpl(
LayerTreeImpl* tree_impl,
int id,
const viz::ViewTransitionElementResourceId& resource_id,
bool is_live_content_layer,
const gfx::RectF& max_extents_rect)
: LayerImpl(tree_impl, id),
resource_id_(resource_id),
is_live_content_layer_(is_live_content_layer),
max_extents_rect_in_originating_layer_coordinate_space_(
max_extents_rect) {}
ViewTransitionContentLayerImpl::~ViewTransitionContentLayerImpl() = default;
mojom::LayerType ViewTransitionContentLayerImpl::GetLayerType() const {
return mojom::LayerType::kViewTransitionContent;
}
std::unique_ptr<LayerImpl> ViewTransitionContentLayerImpl::CreateLayerImpl(
LayerTreeImpl* tree_impl) const {
return ViewTransitionContentLayerImpl::Create(
tree_impl, id(), resource_id_, is_live_content_layer_,
max_extents_rect_in_originating_layer_coordinate_space_);
}
void ViewTransitionContentLayerImpl::NotifyKnownResourceIdsBeforeAppendQuads(
const base::flat_set<viz::ViewTransitionElementResourceId>&
known_resource_ids) {
skip_unseen_resource_quads_ = known_resource_ids.count(resource_id_) == 0;
}
void ViewTransitionContentLayerImpl::PushPropertiesTo(LayerImpl* layer) {
LayerImpl::PushPropertiesTo(layer);
static_cast<ViewTransitionContentLayerImpl*>(layer)->SetMaxExtentsRect(
max_extents_rect_in_originating_layer_coordinate_space_);
}
void ViewTransitionContentLayerImpl::SetOriginatingSurfaceContentRect(
const gfx::Rect&
originating_surface_content_rect_in_layer_coordinate_space) {
if (originating_surface_content_rect_in_layer_coordinate_space.IsEmpty() ||
max_extents_rect_in_originating_layer_coordinate_space_.IsEmpty() ||
gfx::RectF(originating_surface_content_rect_in_layer_coordinate_space) ==
max_extents_rect_in_originating_layer_coordinate_space_) {
actual_extents_rect_ = gfx::Rect();
return;
}
actual_extents_rect_ = gfx::ToRoundedRect(gfx::MapRect(
gfx::RectF(originating_surface_content_rect_in_layer_coordinate_space),
max_extents_rect_in_originating_layer_coordinate_space_,
gfx::RectF(bounds())));
draw_properties().visible_drawable_content_rect.Intersect(
MathUtil::MapEnclosingClippedRect(
draw_properties().target_space_transform, actual_extents_rect_));
}
void ViewTransitionContentLayerImpl::AppendQuads(
const AppendQuadsContext& context,
viz::CompositorRenderPass* render_pass,
AppendQuadsData* append_quads_data) {
if (is_live_content_layer_ && skip_unseen_resource_quads_) {
return;
}
if (resource_id_.MatchesToken(context.capture_view_transition_tokens)) {
return;
}
auto bounds_rect = actual_extents_rect_.IsEmpty() ? gfx::Rect(bounds())
: actual_extents_rect_;
float device_scale_factor = layer_tree_impl()->device_scale_factor();
gfx::Rect quad_rect(
gfx::ScaleToEnclosingRect(bounds_rect, device_scale_factor));
gfx::Rect visible_quad_rect =
draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
bounds_rect);
visible_quad_rect =
gfx::ScaleToEnclosingRect(visible_quad_rect, device_scale_factor);
visible_quad_rect = gfx::IntersectRects(quad_rect, visible_quad_rect);
if (visible_quad_rect.IsEmpty()) {
return;
}
viz::SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
PopulateScaledSharedQuadState(shared_quad_state, device_scale_factor,
contents_opaque());
auto* quad =
render_pass->CreateAndAppendDrawQuad<viz::SharedElementDrawQuad>();
quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, resource_id_);
append_quads_data->has_shared_element_resources = true;
}
viz::ViewTransitionElementResourceId
ViewTransitionContentLayerImpl::ViewTransitionResourceId() const {
return resource_id_;
}
void ViewTransitionContentLayerImpl::SetMaxExtentsRect(
const gfx::RectF& max_extents_rect) {
if (max_extents_rect_in_originating_layer_coordinate_space_ ==
max_extents_rect) {
return;
}
max_extents_rect_in_originating_layer_coordinate_space_ = max_extents_rect;
actual_extents_rect_ = gfx::Rect();
NoteLayerPropertyChanged();
}
}