| // 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/render_target_cache.h" | |
| #include "impeller/renderer/render_target.h" | |
| namespace impeller { | |
| RenderTargetCache::RenderTargetCache(std::shared_ptr<Allocator> allocator) | |
| : RenderTargetAllocator(std::move(allocator)) {} | |
| void RenderTargetCache::Start() { | |
| for (auto& td : render_target_data_) { | |
| td.used_this_frame = false; | |
| } | |
| } | |
| void RenderTargetCache::End() { | |
| std::vector<RenderTargetData> retain; | |
| for (const auto& td : render_target_data_) { | |
| if (td.used_this_frame) { | |
| retain.push_back(td); | |
| } | |
| } | |
| render_target_data_.swap(retain); | |
| } | |
| RenderTarget RenderTargetCache::CreateOffscreen( | |
| const Context& context, | |
| ISize size, | |
| int mip_count, | |
| const std::string& label, | |
| RenderTarget::AttachmentConfig color_attachment_config, | |
| std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config, | |
| const std::shared_ptr<Texture>& existing_color_texture, | |
| const std::shared_ptr<Texture>& existing_depth_stencil_texture) { | |
| if (size.IsEmpty()) { | |
| return {}; | |
| } | |
| FML_DCHECK(existing_color_texture == nullptr && | |
| existing_depth_stencil_texture == nullptr); | |
| auto config = RenderTargetConfig{ | |
| .size = size, | |
| .mip_count = static_cast<size_t>(mip_count), | |
| .has_msaa = false, | |
| .has_depth_stencil = stencil_attachment_config.has_value(), | |
| }; | |
| for (auto& render_target_data : render_target_data_) { | |
| const auto other_config = render_target_data.config; | |
| if (!render_target_data.used_this_frame && other_config == config) { | |
| render_target_data.used_this_frame = true; | |
| auto color0 = render_target_data.render_target.GetColorAttachments() | |
| .find(0u) | |
| ->second; | |
| auto depth = render_target_data.render_target.GetDepthAttachment(); | |
| std::shared_ptr<Texture> depth_tex = depth ? depth->texture : nullptr; | |
| return RenderTargetAllocator::CreateOffscreen( | |
| context, size, mip_count, label, color_attachment_config, | |
| stencil_attachment_config, color0.texture, depth_tex); | |
| } | |
| } | |
| RenderTarget created_target = RenderTargetAllocator::CreateOffscreen( | |
| context, size, mip_count, label, color_attachment_config, | |
| stencil_attachment_config); | |
| if (!created_target.IsValid()) { | |
| return created_target; | |
| } | |
| render_target_data_.push_back( | |
| RenderTargetData{.used_this_frame = true, | |
| .config = config, | |
| .render_target = created_target}); | |
| return created_target; | |
| } | |
| RenderTarget RenderTargetCache::CreateOffscreenMSAA( | |
| const Context& context, | |
| ISize size, | |
| int mip_count, | |
| const std::string& label, | |
| RenderTarget::AttachmentConfigMSAA color_attachment_config, | |
| std::optional<RenderTarget::AttachmentConfig> stencil_attachment_config, | |
| const std::shared_ptr<Texture>& existing_color_msaa_texture, | |
| const std::shared_ptr<Texture>& existing_color_resolve_texture, | |
| const std::shared_ptr<Texture>& existing_depth_stencil_texture) { | |
| if (size.IsEmpty()) { | |
| return {}; | |
| } | |
| FML_DCHECK(existing_color_msaa_texture == nullptr && | |
| existing_color_resolve_texture == nullptr && | |
| existing_depth_stencil_texture == nullptr); | |
| auto config = RenderTargetConfig{ | |
| .size = size, | |
| .mip_count = static_cast<size_t>(mip_count), | |
| .has_msaa = true, | |
| .has_depth_stencil = stencil_attachment_config.has_value(), | |
| }; | |
| for (auto& render_target_data : render_target_data_) { | |
| const auto other_config = render_target_data.config; | |
| if (!render_target_data.used_this_frame && other_config == config) { | |
| render_target_data.used_this_frame = true; | |
| auto color0 = render_target_data.render_target.GetColorAttachments() | |
| .find(0u) | |
| ->second; | |
| auto depth = render_target_data.render_target.GetDepthAttachment(); | |
| std::shared_ptr<Texture> depth_tex = depth ? depth->texture : nullptr; | |
| return RenderTargetAllocator::CreateOffscreenMSAA( | |
| context, size, mip_count, label, color_attachment_config, | |
| stencil_attachment_config, color0.texture, color0.resolve_texture, | |
| depth_tex); | |
| } | |
| } | |
| RenderTarget created_target = RenderTargetAllocator::CreateOffscreenMSAA( | |
| context, size, mip_count, label, color_attachment_config, | |
| stencil_attachment_config); | |
| if (!created_target.IsValid()) { | |
| return created_target; | |
| } | |
| render_target_data_.push_back( | |
| RenderTargetData{.used_this_frame = true, | |
| .config = config, | |
| .render_target = created_target}); | |
| return created_target; | |
| } | |
| size_t RenderTargetCache::CachedTextureCount() const { | |
| return render_target_data_.size(); | |
| } | |
| } // namespace impeller |