[go: nahoru, domu]

blob: e2268671e2aa76929e70a5f9780f521a902bcaae [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/layer.h"
#include <algorithm>
#include <atomic>
#include <utility>
#include "base/atomic_sequence_num.h"
#include "base/check.h"
#include "base/containers/cxx20_erase_vector.h"
#include "base/ranges/algorithm.h"
#include "cc/layers/layer.h"
#include "cc/paint/filter_operation.h"
#include "cc/paint/filter_operations.h"
#include "cc/slim/features.h"
#include "cc/slim/layer_tree.h"
#include "cc/slim/layer_tree_impl.h"
#include "components/viz/common/quads/shared_quad_state.h"
namespace cc::slim {
namespace {
base::AtomicSequenceNumber g_next_id;
cc::FilterOperations ToCcFilters(std::vector<cc::slim::Filter> filters) {
cc::FilterOperations cc_filters;
for (const auto& slim_filter : filters) {
switch (slim_filter.type()) {
case cc::slim::Filter::kBrightness:
cc_filters.Append(
cc::FilterOperation::CreateBrightnessFilter(slim_filter.amount()));
break;
case cc::slim::Filter::kSaturation:
cc_filters.Append(
cc::FilterOperation::CreateSaturateFilter(slim_filter.amount()));
break;
}
}
return cc_filters;
}
} // namespace
// static
scoped_refptr<Layer> Layer::Create() {
scoped_refptr<cc::Layer> cc_layer;
if (!features::IsSlimCompositorEnabled()) {
cc_layer = cc::Layer::Create();
}
return base::AdoptRef(new Layer(std::move(cc_layer)));
}
Layer::Layer(scoped_refptr<cc::Layer> cc_layer)
: cc_layer_(std::move(cc_layer)),
id_(g_next_id.GetNext() + 1),
is_drawable_(false),
contents_opaque_(false),
draws_content_(false),
hide_layer_and_subtree_(false),
masks_to_bounds_(false) {}
Layer::~Layer() {
RemoveAllChildren();
}
void Layer::SetLayerTree(LayerTree* layer_tree) {
if (layer_tree_ == layer_tree) {
return;
}
layer_tree_ = layer_tree;
for (auto& child : children_) {
child->SetLayerTree(layer_tree);
}
}
Layer* Layer::RootLayer() {
Layer* layer = this;
while (layer->parent_) {
layer = layer->parent_;
}
return layer;
}
void Layer::AddChild(scoped_refptr<Layer> child) {
if (cc_layer()) {
cc_layer()->AddChild(child->cc_layer());
}
InsertChildSlim(std::move(child), children_.size());
}
void Layer::InsertChild(scoped_refptr<Layer> child, size_t position) {
if (cc_layer()) {
cc_layer()->InsertChild(child->cc_layer(), position);
}
InsertChildSlim(std::move(child), position);
}
void Layer::InsertChildSlim(scoped_refptr<Layer> child, size_t position) {
WillAddChildSlim(child.get());
const size_t index = std::min(position, children_.size());
children_.insert(children_.begin() + index, std::move(child));
NotifyTreeChanged();
}
void Layer::WillAddChildSlim(Layer* child) {
child->RemoveFromParentSlim();
child->parent_ = this;
child->SetLayerTree(layer_tree());
}
void Layer::ReplaceChild(Layer* old_child, scoped_refptr<Layer> new_child) {
if (cc_layer()) {
cc_layer()->ReplaceChild(old_child->cc_layer(),
new_child ? new_child->cc_layer() : nullptr);
}
if (old_child->parent_ != this || old_child == new_child.get()) {
return;
}
auto it = base::ranges::find_if(
children_, [&](auto& ptr) { return ptr.get() == old_child; });
DCHECK(it != children_.end());
old_child->parent_ = nullptr;
old_child->SetLayerTree(nullptr);
if (new_child) {
WillAddChildSlim(new_child.get());
*it = std::move(new_child);
} else {
children_.erase(it);
}
NotifyTreeChanged();
}
void Layer::RemoveFromParent() {
if (cc_layer()) {
cc_layer()->RemoveFromParent();
}
RemoveFromParentSlim();
}
void Layer::RemoveFromParentSlim() {
if (!parent_) {
return;
}
SetLayerTree(nullptr);
base::EraseIf(parent_->children_,
[&](auto& ptr) { return ptr.get() == this; });
parent_->NotifyTreeChanged();
parent_ = nullptr;
}
void Layer::RemoveAllChildren() {
if (cc_layer()) {
cc_layer()->RemoveAllChildren();
}
if (children_.empty()) {
return;
}
for (auto& child : children_) {
child->SetLayerTree(nullptr);
child->parent_ = nullptr;
}
children_.clear();
NotifyTreeChanged();
}
bool Layer::HasAncestor(Layer* layer) const {
for (Layer* ancestor = parent_; ancestor; ancestor = ancestor->parent_) {
if (ancestor == layer) {
DCHECK(!cc_layer() || cc_layer()->HasAncestor(layer->cc_layer()));
return true;
}
}
DCHECK(!cc_layer() || !cc_layer()->HasAncestor(layer->cc_layer()));
return false;
}
void Layer::SetPosition(const gfx::PointF& position) {
if (cc_layer()) {
cc_layer()->SetPosition(position);
return;
}
if (position_ == position) {
return;
}
position_ = position;
NotifyPropertyChanged();
}
const gfx::PointF Layer::position() const {
return cc_layer() ? cc_layer()->position() : position_;
}
void Layer::SetBounds(const gfx::Size& bounds) {
if (cc_layer()) {
cc_layer()->SetBounds(bounds);
return;
}
if (bounds_ == bounds) {
return;
}
bounds_ = bounds;
NotifyPropertyChanged();
}
const gfx::Size& Layer::bounds() const {
return cc_layer() ? cc_layer()->bounds() : bounds_;
}
void Layer::SetTransform(const gfx::Transform& transform) {
if (cc_layer()) {
cc_layer()->SetTransform(transform);
return;
}
if (transform_ == transform) {
return;
}
transform_ = transform;
NotifyPropertyChanged();
}
const gfx::Transform& Layer::transform() const {
return cc_layer() ? cc_layer()->transform() : transform_;
}
void Layer::SetTransformOrigin(const gfx::Point3F& origin) {
if (cc_layer()) {
cc_layer()->SetTransformOrigin(origin);
return;
}
if (transform_origin_ == origin) {
return;
}
transform_origin_ = origin;
NotifyPropertyChanged();
}
gfx::Point3F Layer::transform_origin() const {
return cc_layer() ? cc_layer()->transform_origin() : transform_origin_;
}
void Layer::SetIsDrawable(bool drawable) {
if (cc_layer()) {
cc_layer()->SetIsDrawable(drawable);
return;
}
if (is_drawable_ == drawable) {
return;
}
is_drawable_ = drawable;
SetDrawsContent(HasDrawableContent());
}
void Layer::SetBackgroundColor(SkColor4f color) {
if (cc_layer()) {
cc_layer()->SetBackgroundColor(color);
return;
}
if (background_color_ == color) {
return;
}
background_color_ = color;
NotifyPropertyChanged();
}
SkColor4f Layer::background_color() const {
return cc_layer() ? cc_layer()->background_color() : background_color_;
}
void Layer::SetContentsOpaque(bool opaque) {
if (cc_layer()) {
cc_layer()->SetContentsOpaque(opaque);
return;
}
if (contents_opaque_ == opaque) {
return;
}
contents_opaque_ = opaque;
NotifyPropertyChanged();
}
bool Layer::contents_opaque() const {
return cc_layer() ? cc_layer()->contents_opaque() : contents_opaque_;
}
void Layer::SetOpacity(float opacity) {
if (cc_layer()) {
cc_layer()->SetOpacity(opacity);
return;
}
if (opacity_ == opacity) {
return;
}
opacity_ = opacity;
NotifyPropertyChanged();
}
float Layer::opacity() const {
return cc_layer() ? cc_layer()->opacity() : opacity_;
}
bool Layer::draws_content() const {
return cc_layer() ? cc_layer()->draws_content() : draws_content_;
}
void Layer::SetDrawsContent(bool value) {
if (cc_layer()) {
cc_layer()->SetDrawsContent(value);
return;
}
if (draws_content_ == value) {
return;
}
draws_content_ = value;
NotifyPropertyChanged();
}
void Layer::SetHideLayerAndSubtree(bool hide) {
if (cc_layer()) {
cc_layer()->SetHideLayerAndSubtree(hide);
return;
}
if (hide_layer_and_subtree_ == hide) {
return;
}
hide_layer_and_subtree_ = hide;
NotifyPropertyChanged();
}
bool Layer::hide_layer_and_subtree() const {
return cc_layer() ? cc_layer()->hide_layer_and_subtree()
: hide_layer_and_subtree_;
}
void Layer::SetMasksToBounds(bool masks_to_bounds) {
if (cc_layer()) {
cc_layer()->SetMasksToBounds(masks_to_bounds);
return;
}
if (masks_to_bounds_ == masks_to_bounds) {
return;
}
masks_to_bounds_ = masks_to_bounds;
NotifyPropertyChanged();
}
bool Layer::masks_to_bounds() const {
return cc_layer() ? cc_layer()->masks_to_bounds() : masks_to_bounds_;
}
void Layer::SetFilters(std::vector<Filter> filters) {
if (cc_layer()) {
cc_layer()->SetFilters(ToCcFilters(std::move(filters)));
return;
}
if (filters_ == filters) {
return;
}
filters_ = std::move(filters);
NotifyPropertyChanged();
}
bool Layer::HasDrawableContent() const {
return is_drawable_;
}
gfx::Transform Layer::ComputeTransformToParent() {
// Layer transform is:
// position x transform_origin x transform x -transform_origin
gfx::Transform transform =
gfx::Transform::MakeTranslation(position_.x(), position_.y());
transform.Translate3d(transform_origin_.x(), transform_origin_.y(),
transform_origin_.z());
transform.PreConcat(transform_);
transform.Translate3d(-transform_origin_.x(), -transform_origin_.y(),
-transform_origin_.z());
return transform;
}
void Layer::AppendQuads(viz::CompositorRenderPass& render_pass,
const gfx::Transform& transform,
const gfx::Rect* clip) {}
void Layer::NotifyTreeChanged() {
if (cc_layer()) {
return;
}
if (layer_tree_) {
static_cast<LayerTreeImpl*>(layer_tree_)->NotifyTreeChanged();
}
}
void Layer::NotifyPropertyChanged() {
DCHECK(!cc_layer());
if (layer_tree_) {
static_cast<LayerTreeImpl*>(layer_tree_)->NotifyPropertyChanged();
}
}
viz::SharedQuadState* Layer::CreateAndAppendSharedQuadState(
viz::CompositorRenderPass& render_pass,
const gfx::Transform& transform,
const gfx::Rect* clip) {
viz::SharedQuadState* quad_state =
render_pass.CreateAndAppendSharedQuadState();
const gfx::Rect rect{bounds()};
absl::optional<gfx::Rect> clip_opt;
if (clip) {
clip_opt = *clip;
}
// TODO(crbug.com/1408128): Set visible_layer_rect properly.
quad_state->SetAll(transform, /*layer_rect=*/rect,
/*visible_layer_rect=*/rect, gfx::MaskFilterInfo(),
std::move(clip_opt), contents_opaque(), opacity(),
SkBlendMode::kSrcOver, 0);
return quad_state;
}
} // namespace cc::slim