blob: f5da62830ecbcc1748b9b36319c6dc153d33693d [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/scene_contents.h"
#include "impeller/core/formats.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/tiled_texture_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/scene/camera.h"
#include "impeller/scene/scene.h"
namespace impeller {
SceneContents::SceneContents() = default;
SceneContents::~SceneContents() = default;
void SceneContents::SetCameraTransform(Matrix matrix) {
camera_transform_ = matrix;
}
void SceneContents::SetNode(std::shared_ptr<scene::Node> node) {
node_ = std::move(node);
}
bool SceneContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (!node_) {
return true;
}
auto coverage = GetCoverage(entity);
if (!coverage.has_value()) {
return true;
}
// This happens for CoverGeometry (DrawPaint). In this situation,
// Draw the scene to the full layer.
if (coverage.value().IsMaximum()) {
coverage = Rect::MakeSize(pass.GetRenderTargetSize());
}
RenderTarget subpass_target;
if (renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
subpass_target = RenderTarget::CreateOffscreenMSAA(
*renderer.GetContext(), // context
*renderer.GetRenderTargetCache(), // allocator
ISize(coverage.value().GetSize()), // size
/*mip_count=*/1,
"SceneContents", // label
RenderTarget::AttachmentConfigMSAA{
.storage_mode = StorageMode::kDeviceTransient,
.resolve_storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kMultisampleResolve,
}, // color_attachment_config
RenderTarget::AttachmentConfig{
.storage_mode = StorageMode::kDeviceTransient,
.load_action = LoadAction::kDontCare,
.store_action = StoreAction::kDontCare,
} // stencil_attachment_config
);
} else {
subpass_target = RenderTarget::CreateOffscreen(
*renderer.GetContext(), // context
*renderer.GetRenderTargetCache(), // allocator
ISize(coverage.value().GetSize()), // size
/*mip_count=*/1,
"SceneContents", // label
RenderTarget::AttachmentConfig{
.storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kStore,
}, // color_attachment_config
RenderTarget::AttachmentConfig{
.storage_mode = StorageMode::kDeviceTransient,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kDontCare,
} // stencil_attachment_config
);
}
if (!subpass_target.IsValid()) {
return false;
}
scene::Scene scene(renderer.GetSceneContext());
scene.GetRoot().AddChild(node_);
if (!scene.Render(subpass_target, camera_transform_)) {
return false;
}
// Render the texture to the pass.
TiledTextureContents contents;
contents.SetGeometry(GetGeometry());
contents.SetTexture(subpass_target.GetRenderTargetTexture());
contents.SetEffectTransform(
Matrix::MakeScale(1 / entity.GetTransform().GetScale()));
return contents.Render(renderer, entity, pass);
}
} // namespace impeller