blob: 9e37aa7b2d99077edd131638224bbf6b0594e261 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/compositor/layer_surface.h"
#include <algorithm>
#include <utility>
#include "base/notreached.h"
#include "cc/layers/surface_layer.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "ui/compositor/layer_mirror.h"
namespace ui {
LayerSurface::LayerSurface() : Layer(LAYER_SURFACE) {
surface_layer_ = cc::SurfaceLayer::Create();
cc_layer_ = surface_layer_.get();
InitializeCcLayer();
surface_layer_->SetSurfaceHitTestable(true);
}
LayerSurface::~LayerSurface() {
Destroy();
}
bool LayerSurface::ShouldSchedulePaint() const {
return false;
}
void LayerSurface::SetFallbackBackgroundColor(SkColor4f color) {
surface_layer_->SetBackgroundColor(color);
surface_layer_->SetSafeOpaqueBackgroundColor(color);
for (const auto& mirror : mirrors_) {
mirror->dest()->AsSurface()->SetFallbackBackgroundColor(color);
}
}
SkColor4f LayerSurface::GetFallbackBackgroundColor() const {
return surface_layer_->background_color();
}
std::unique_ptr<Layer> LayerSurface::Clone() const {
auto clone = Layer::Clone();
auto* cloned_surface = clone->AsSurface();
cloned_surface->SetFallbackBackgroundColor(
surface_layer_->background_color());
cloned_surface->SetShowSurface(
surface_layer_->surface_id(), frame_size_in_dip_,
surface_layer_->deadline_in_frames()
? cc::DeadlinePolicy::UseSpecifiedDeadline(
*surface_layer_->deadline_in_frames())
: cc::DeadlinePolicy::UseDefaultDeadline(),
surface_layer_->stretch_content_to_fill_bounds());
if (surface_layer_->oldest_acceptable_fallback()) {
cloned_surface->SetOldestAcceptableFallback(
*surface_layer_->oldest_acceptable_fallback());
}
return clone;
}
void LayerSurface::SetShowSurface(const viz::SurfaceId& surface_id,
const gfx::Size& frame_size_in_dip,
const cc::DeadlinePolicy& deadline_policy,
bool stretch_content_to_fill_bounds) {
surface_layer_->SetSurfaceId(surface_id, deadline_policy);
surface_layer_->SetStretchContentToFillBounds(stretch_content_to_fill_bounds);
frame_size_in_dip_ = frame_size_in_dip;
RecomputeDrawsContentAndUVRect();
for (const auto& mirror : mirrors_) {
mirror->dest()->AsSurface()->SetShowSurface(surface_id, frame_size_in_dip,
deadline_policy,
stretch_content_to_fill_bounds);
}
}
void LayerSurface::SetShowSurface(const viz::SurfaceId& surface_id,
const cc::DeadlinePolicy& deadline_policy,
bool stretch_content_to_fill_bounds) {
// Assumes `frame_size_in_dip_` is already set.
// TODO(crbug.com/40285157): with surface sync, it should use on `bounds_`.
surface_layer_->SetSurfaceId(surface_id, deadline_policy);
surface_layer_->SetStretchContentToFillBounds(stretch_content_to_fill_bounds);
for (const auto& mirror : mirrors_) {
mirror->dest()->AsSurface()->SetShowSurface(surface_id, deadline_policy,
stretch_content_to_fill_bounds);
}
}
void LayerSurface::SetShowReflectedSurface(
const viz::SurfaceId& surface_id,
const gfx::Size& frame_size_in_pixels) {
surface_layer_->SetSurfaceId(surface_id,
cc::DeadlinePolicy::UseInfiniteDeadline());
// Set the fallback color (also used for gutters) as kBlack.
surface_layer_->SetBackgroundColor(SkColors::kBlack);
surface_layer_->SetSafeOpaqueBackgroundColor(SkColors::kBlack);
surface_layer_->SetStretchContentToFillBounds(true);
surface_layer_->SetIsReflection(true);
// The reflecting surface uses the native size of the reflected display.
frame_size_in_dip_ = frame_size_in_pixels;
RecomputeDrawsContentAndUVRect();
}
void LayerSurface::SetOldestAcceptableFallback(
const viz::SurfaceId& surface_id) {
surface_layer_->SetOldestAcceptableFallback(surface_id);
for (const auto& mirror : mirrors_) {
mirror->dest()->AsSurface()->SetOldestAcceptableFallback(surface_id);
}
}
const viz::SurfaceId* LayerSurface::GetOldestAcceptableFallback() const {
if (surface_layer_->oldest_acceptable_fallback()) {
return &surface_layer_->oldest_acceptable_fallback().value();
}
return nullptr;
}
bool LayerSurface::StretchContentToFillBounds() const {
return surface_layer_->stretch_content_to_fill_bounds();
}
void LayerSurface::SetSurfaceSize(gfx::Size surface_size_in_dip) {
if (frame_size_in_dip_ == surface_size_in_dip) {
return;
}
frame_size_in_dip_ = surface_size_in_dip;
RecomputeDrawsContentAndUVRect();
}
const viz::SurfaceId* LayerSurface::GetSurfaceId() const {
if (surface_layer_->surface_id().is_valid()) {
return &surface_layer_->surface_id();
}
return nullptr;
}
void LayerSurface::RecomputeDrawsContentAndUVRect() {
gfx::Size size(bounds_.size());
// TODO(crbug.com/40285157): with surface sync, size shouldn't rely on
// `frame_size_in_dip_` anymore.
size.SetToMin(frame_size_in_dip_);
cc_layer_->SetBounds(size);
}
void LayerSurface::Reset() {
surface_layer_ = nullptr;
}
void LayerSurface::OnPaintScheduled() {
NOTREACHED();
}
} // namespace ui