blob: d153ea1bc9b7c624589ec78452756b7c1b90f7b3 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/entity/contents/contents.h"
#include <optional>
#include "fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/entity/contents/anonymous_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/render_pass.h"
namespace impeller {
ContentContextOptions OptionsFromPass(const RenderPass& pass) {
ContentContextOptions opts;
opts.sample_count = pass.GetSampleCount();
opts.color_attachment_pixel_format = pass.GetRenderTargetPixelFormat();
bool has_depth_stencil_attachments =
pass.HasDepthAttachment() && pass.HasStencilAttachment();
FML_DCHECK(pass.HasDepthAttachment() == pass.HasStencilAttachment());
opts.has_depth_stencil_attachments = has_depth_stencil_attachments;
opts.depth_compare = CompareFunction::kGreaterEqual;
opts.stencil_mode = ContentContextOptions::StencilMode::kIgnore;
return opts;
}
ContentContextOptions OptionsFromPassAndEntity(const RenderPass& pass,
const Entity& entity) {
ContentContextOptions opts = OptionsFromPass(pass);
opts.blend_mode = entity.GetBlendMode();
return opts;
}
std::shared_ptr<Contents> Contents::MakeAnonymous(
Contents::RenderProc render_proc,
Contents::CoverageProc coverage_proc) {
return AnonymousContents::Make(std::move(render_proc),
std::move(coverage_proc));
}
Contents::Contents() = default;
Contents::~Contents() = default;
bool Contents::IsOpaque(const Matrix& transform) const {
return false;
}
std::optional<Snapshot> Contents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
const Contents::SnapshotOptions& options) const {
auto coverage = GetCoverage(entity);
if (!coverage.has_value()) {
return std::nullopt;
}
std::shared_ptr<CommandBuffer> command_buffer =
renderer.GetContext()->CreateCommandBuffer();
if (!command_buffer) {
return std::nullopt;
}
// Pad Contents snapshots with 1 pixel borders to ensure correct sampling
// behavior. Not doing so results in a coverage leak for filters that support
// customizing the input sampling mode. Snapshots of contents should be
// theoretically treated as infinite size just like layers.
coverage = coverage->Expand(options.coverage_expansion);
if (options.coverage_limit.has_value()) {
coverage = coverage->Intersection(*options.coverage_limit);
if (!coverage.has_value()) {
return std::nullopt;
}
}
ISize subpass_size = ISize::Ceil(coverage->GetSize());
fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
options.label, subpass_size, command_buffer,
[&contents = *this, &entity, &coverage](const ContentContext& renderer,
RenderPass& pass) -> bool {
Entity sub_entity;
sub_entity.SetBlendMode(BlendMode::kSrcOver);
sub_entity.SetTransform(
Matrix::MakeTranslation(Vector3(-coverage->GetOrigin())) *
entity.GetTransform());
return contents.Render(renderer, sub_entity, pass);
},
options.msaa_enabled, /*depth_stencil_enabled=*/true,
std::min(options.mip_count,
static_cast<int32_t>(subpass_size.MipCount())));
if (!render_target.ok()) {
return std::nullopt;
}
if (!renderer.GetContext()->EnqueueCommandBuffer(std::move(command_buffer))) {
return std::nullopt;
}
auto snapshot = Snapshot{
.texture = render_target.value().GetRenderTargetTexture(),
.transform = Matrix::MakeTranslation(coverage->GetOrigin()),
};
if (options.sampler_descriptor.has_value()) {
snapshot.sampler_descriptor = options.sampler_descriptor.value();
}
return snapshot;
}
void Contents::SetInheritedOpacity(Scalar opacity) {
VALIDATION_LOG << "Contents::SetInheritedOpacity should never be called when "
"Contents::CanAcceptOpacity returns false.";
}
std::optional<Color> Contents::AsBackgroundColor(const Entity& entity,
ISize target_size) const {
return {};
}
bool Contents::ApplyColorFilter(
const Contents::ColorFilterProc& color_filter_proc) {
return false;
}
void Contents::SetCoverageHint(std::optional<Rect> coverage_hint) {
coverage_hint_ = coverage_hint;
}
const std::optional<Rect>& Contents::GetCoverageHint() const {
return coverage_hint_;
}
std::optional<Size> Contents::GetColorSourceSize() const {
return color_source_size_;
};
void Contents::SetColorSourceSize(Size size) {
color_source_size_ = size;
}
} // namespace impeller