| // 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 = renderer.GetRenderTargetCache()->CreateOffscreenMSAA( |
| *renderer.GetContext(), // context |
| 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 = renderer.GetRenderTargetCache()->CreateOffscreen( |
| *renderer.GetContext(), // context |
| 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 |