From 72fb1b83a80e82f6a783220a9c1838c6fd9e04da Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 3 Jun 2023 21:37:45 -0700 Subject: [PATCH 1/2] [Impeller] Reland: Add Impeller Metal support in the embedder API (#42411) This reverts commit 05f958c7f3b1c66d543e9170d54ecc1b5a253df4. --- ci/licenses_golden/licenses_flutter | 16 ++ flow/BUILD.gn | 5 + flow/embedded_views.cc | 6 +- flow/embedded_views.h | 17 +- .../backend/metal/playground_impl_mtl.mm | 2 +- impeller/renderer/backend/metal/BUILD.gn | 2 + impeller/renderer/backend/metal/context_mtl.h | 15 ++ .../renderer/backend/metal/context_mtl.mm | 61 +++-- impeller/renderer/backend/metal/surface_mtl.h | 12 +- .../renderer/backend/metal/surface_mtl.mm | 164 +++++++++---- impeller/renderer/backend/metal/texture_mtl.h | 6 +- .../renderer/backend/metal/texture_mtl.mm | 22 +- .../backend/metal/texture_wrapper_mtl.h | 16 ++ .../backend/metal/texture_wrapper_mtl.mm | 22 ++ shell/common/rasterizer.cc | 4 +- shell/common/rasterizer_unittests.cc | 3 +- .../shell_test_external_view_embedder.cc | 1 + .../shell_test_external_view_embedder.h | 1 + shell/gpu/gpu_surface_metal_impeller.h | 26 +- shell/gpu/gpu_surface_metal_impeller.mm | 159 ++++++++++-- .../external_view_embedder.cc | 1 + .../external_view_embedder.h | 1 + .../external_view_embedder_unittests.cc | 18 +- .../darwin/ios/ios_external_view_embedder.h | 1 + .../darwin/ios/ios_external_view_embedder.mm | 6 +- shell/platform/embedder/BUILD.gn | 24 +- shell/platform/embedder/embedder.cc | 229 ++++++++++++++---- .../embedder/embedder_external_view.cc | 31 ++- .../embedder_external_view_embedder.cc | 5 +- .../embedder_external_view_embedder.h | 3 + .../embedder/embedder_render_target.cc | 15 +- .../embedder/embedder_render_target.h | 70 ++++-- .../embedder/embedder_render_target_cache.cc | 3 +- .../embedder_render_target_impeller.cc | 45 ++++ .../embedder_render_target_impeller.h | 44 ++++ .../embedder/embedder_render_target_skia.cc | 40 +++ .../embedder/embedder_render_target_skia.h | 41 ++++ shell/platform/embedder/embedder_surface.cc | 9 + shell/platform/embedder/embedder_surface.h | 5 +- .../embedder_surface_metal_impeller.h | 70 ++++++ .../embedder_surface_metal_impeller.mm | 97 ++++++++ .../embedder/platform_view_embedder.cc | 7 +- .../embedder/platform_view_embedder.h | 5 +- .../flatland_external_view_embedder.cc | 1 + .../flutter/flatland_external_view_embedder.h | 1 + .../flutter/gfx_external_view_embedder.cc | 1 + .../flutter/gfx_external_view_embedder.h | 1 + .../fuchsia/flutter/platform_view_unittest.cc | 1 + ...atland_external_view_embedder_unittests.cc | 22 +- .../tests/flatland_platform_view_unittest.cc | 1 + .../gfx_external_view_embedder_unittests.cc | 22 +- 51 files changed, 1154 insertions(+), 226 deletions(-) create mode 100644 impeller/renderer/backend/metal/texture_wrapper_mtl.h create mode 100644 impeller/renderer/backend/metal/texture_wrapper_mtl.mm create mode 100644 shell/platform/embedder/embedder_render_target_impeller.cc create mode 100644 shell/platform/embedder/embedder_render_target_impeller.h create mode 100644 shell/platform/embedder/embedder_render_target_skia.cc create mode 100644 shell/platform/embedder/embedder_render_target_skia.h create mode 100644 shell/platform/embedder/embedder_surface_metal_impeller.h create mode 100644 shell/platform/embedder/embedder_surface_metal_impeller.mm diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index a98cab24c4da3..183aeecc56e35 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1485,6 +1485,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/metal/surface_mtl.h + ../../. ORIGIN: ../../../flutter/impeller/renderer/backend/metal/surface_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/texture_mtl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/texture_mtl.mm + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/metal/texture_wrapper_mtl.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/renderer/backend/metal/texture_wrapper_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc + ../../../flutter/LICENSE @@ -2804,6 +2806,10 @@ ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target.cc + ../ ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_cache.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_cache.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_struct_macros.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface.h + ../../../flutter/LICENSE @@ -2811,6 +2817,8 @@ ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_gl.cc + ../../ ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_gl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_metal.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_metal.mm + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_metal_impeller.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_metal_impeller.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_software.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc + ../../../flutter/LICENSE @@ -4154,6 +4162,8 @@ FILE: ../../../flutter/impeller/renderer/backend/metal/surface_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/surface_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/metal/texture_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/texture_mtl.mm +FILE: ../../../flutter/impeller/renderer/backend/metal/texture_wrapper_mtl.h +FILE: ../../../flutter/impeller/renderer/backend/metal/texture_wrapper_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc @@ -5489,6 +5499,10 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.cc FILE: ../../../flutter/shell/platform/embedder/embedder_render_target.h FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_cache.cc FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_cache.h +FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.cc +FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.h +FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.cc +FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.h FILE: ../../../flutter/shell/platform/embedder/embedder_struct_macros.h FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h @@ -5496,6 +5510,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.cc FILE: ../../../flutter/shell/platform/embedder/embedder_surface_gl.h FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal.h FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal.mm +FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal_impeller.h +FILE: ../../../flutter/shell/platform/embedder/embedder_surface_metal_impeller.mm FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc diff --git a/flow/BUILD.gn b/flow/BUILD.gn index efda895393f26..560b067e7e22b 100644 --- a/flow/BUILD.gn +++ b/flow/BUILD.gn @@ -4,6 +4,7 @@ import("//build/fuchsia/sdk.gni") import("//flutter/common/config.gni") +import("//flutter/impeller/tools/impeller.gni") import("//flutter/shell/config.gni") import("//flutter/testing/testing.gni") @@ -96,6 +97,10 @@ source_set("flow") { "//third_party/skia", ] + if (impeller_supports_rendering) { + deps += [ "//flutter/impeller" ] + } + public_deps = [ "//flutter/display_list" ] } diff --git a/flow/embedded_views.cc b/flow/embedded_views.cc index b76c9730af903..c19f1c198e3e3 100644 --- a/flow/embedded_views.cc +++ b/flow/embedded_views.cc @@ -42,8 +42,10 @@ bool DisplayListEmbedderViewSlice::recording_ended() { return builder_ == nullptr; } -void ExternalViewEmbedder::SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) { +void ExternalViewEmbedder::SubmitFrame( + GrDirectContext* context, + const std::shared_ptr& aiks_context, + std::unique_ptr frame) { frame->Submit(); }; diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 4162e79a15af6..5293babc419a9 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_FLOW_EMBEDDED_VIEWS_H_ #define FLUTTER_FLOW_EMBEDDED_VIEWS_H_ +#include #include #include "flutter/display_list/dl_builder.h" @@ -22,6 +23,16 @@ #include "third_party/skia/include/core/SkSize.h" #include "third_party/skia/include/core/SkSurface.h" +#if IMPELLER_SUPPORTS_RENDERING +#include "flutter/impeller/aiks/aiks_context.h" // nogncheck +#include "flutter/impeller/renderer/context.h" // nogncheck +#else // IMPELLER_SUPPORTS_RENDERING +namespace impeller { +class Context; +class AiksContext; +} // namespace impeller +#endif // !IMPELLER_SUPPORTS_RENDERING + class GrDirectContext; namespace flutter { @@ -414,8 +425,10 @@ class ExternalViewEmbedder { // This method can mutate the root Skia canvas before submitting the frame. // // It can also allocate frames for overlay surfaces to compose hybrid views. - virtual void SubmitFrame(GrDirectContext* context, - std::unique_ptr frame); + virtual void SubmitFrame( + GrDirectContext* context, + const std::shared_ptr& aiks_context, + std::unique_ptr frame); // This method provides the embedder a way to do additional tasks after // |SubmitFrame|. For example, merge task runners if `should_resubmit_frame` diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 25f108666ebe0..55e17871f70a5 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -121,7 +121,7 @@ auto drawable = SurfaceMTL::GetMetalDrawableAndValidate(context, data_->metal_layer); - return SurfaceMTL::WrapCurrentMetalLayerDrawable(context, drawable); + return SurfaceMTL::MakeFromMetalLayerDrawable(context, drawable); } } // namespace impeller diff --git a/impeller/renderer/backend/metal/BUILD.gn b/impeller/renderer/backend/metal/BUILD.gn index 7ad03e9cea138..9a0f6a631e3d7 100644 --- a/impeller/renderer/backend/metal/BUILD.gn +++ b/impeller/renderer/backend/metal/BUILD.gn @@ -42,6 +42,8 @@ impeller_component("metal") { "surface_mtl.mm", "texture_mtl.h", "texture_mtl.mm", + "texture_wrapper_mtl.h", + "texture_wrapper_mtl.mm", "vertex_descriptor_mtl.h", "vertex_descriptor_mtl.mm", ] diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index fe461601daf06..820c0e216e2de 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -21,6 +21,12 @@ #include "impeller/renderer/capabilities.h" #include "impeller/renderer/context.h" +#if TARGET_OS_SIMULATOR +#define IMPELLER_CA_METAL_LAYER_AVAILABLE API_AVAILABLE(macos(10.11), ios(13.0)) +#else // TARGET_OS_SIMULATOR +#define IMPELLER_CA_METAL_LAYER_AVAILABLE API_AVAILABLE(macos(10.11), ios(8.0)) +#endif // TARGET_OS_SIMULATOR + namespace impeller { class ContextMTL final : public Context, @@ -38,6 +44,14 @@ class ContextMTL final : public Context, std::shared_ptr is_gpu_disabled_sync_switch, const std::string& label); + static std::shared_ptr Create( + id device, + id command_queue, + const std::vector>& shader_libraries_data, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch, + const std::string& label); + // |Context| ~ContextMTL() override; @@ -90,6 +104,7 @@ class ContextMTL final : public Context, ContextMTL( id device, + id command_queue, NSArray>* shader_libraries, std::shared_ptr worker_task_runner, std::shared_ptr is_gpu_disabled_sync_switch); diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index d24ddae9569d2..cc4ea365cab42 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -6,9 +6,11 @@ #include +#include "flutter/fml/concurrent_message_loop.h" #include "flutter/fml/file.h" #include "flutter/fml/logging.h" #include "flutter/fml/paths.h" +#include "flutter/fml/synchronization/sync_switch.h" #include "impeller/core/sampler_descriptor.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h" #include "impeller/renderer/capabilities.h" @@ -67,10 +69,12 @@ static bool DeviceSupportsComputeSubgroups(id device) { ContextMTL::ContextMTL( id device, + id command_queue, NSArray>* shader_libraries, std::shared_ptr worker_task_runner, std::shared_ptr is_gpu_disabled_sync_switch) : device_(device), + command_queue_(command_queue), worker_task_runner_(std::move(worker_task_runner)), is_gpu_disabled_sync_switch_(std::move(is_gpu_disabled_sync_switch)) { // Validate device. @@ -96,16 +100,6 @@ static bool DeviceSupportsComputeSubgroups(id device) { shader_library_ = std::move(library); } - // Setup command queue. - { - command_queue_ = device_.newCommandQueue; - if (!command_queue_) { - VALIDATION_LOG << "Could not setup the command queue."; - return; - } - command_queue_.label = @"Impeller Command Queue"; - } - // Setup the pipeline library. { pipeline_library_ = @@ -204,13 +198,28 @@ static bool DeviceSupportsComputeSubgroups(id device) { return ::MTLCreateSystemDefaultDevice(); } +static id CreateMetalCommandQueue(id device) { + auto command_queue = device.newCommandQueue; + if (!command_queue) { + VALIDATION_LOG << "Could not setup the command queue."; + return nullptr; + } + command_queue.label = @"Impeller Command Queue"; + return command_queue; +} + std::shared_ptr ContextMTL::Create( const std::vector& shader_library_paths, std::shared_ptr worker_task_runner, std::shared_ptr is_gpu_disabled_sync_switch) { auto device = CreateMetalDevice(); + auto command_queue = CreateMetalCommandQueue(device); + if (!command_queue) { + return nullptr; + } auto context = std::shared_ptr(new ContextMTL( - device, MTLShaderLibraryFromFilePaths(device, shader_library_paths), + device, command_queue, + MTLShaderLibraryFromFilePaths(device, shader_library_paths), std::move(worker_task_runner), std::move(is_gpu_disabled_sync_switch))); if (!context->IsValid()) { FML_LOG(ERROR) << "Could not create Metal context."; @@ -223,11 +232,35 @@ static bool DeviceSupportsComputeSubgroups(id device) { const std::vector>& shader_libraries_data, std::shared_ptr worker_task_runner, std::shared_ptr is_gpu_disabled_sync_switch, - const std::string& label) { + const std::string& library_label) { auto device = CreateMetalDevice(); + auto command_queue = CreateMetalCommandQueue(device); + if (!command_queue) { + return nullptr; + } + auto context = std::shared_ptr(new ContextMTL( + device, command_queue, + MTLShaderLibraryFromFileData(device, shader_libraries_data, + library_label), + std::move(worker_task_runner), std::move(is_gpu_disabled_sync_switch))); + if (!context->IsValid()) { + FML_LOG(ERROR) << "Could not create Metal context."; + return nullptr; + } + return context; +} + +std::shared_ptr ContextMTL::Create( + id device, + id command_queue, + const std::vector>& shader_libraries_data, + std::shared_ptr worker_task_runner, + std::shared_ptr is_gpu_disabled_sync_switch, + const std::string& library_label) { auto context = std::shared_ptr(new ContextMTL( - device, - MTLShaderLibraryFromFileData(device, shader_libraries_data, label), + device, command_queue, + MTLShaderLibraryFromFileData(device, shader_libraries_data, + library_label), std::move(worker_task_runner), std::move(is_gpu_disabled_sync_switch))); if (!context->IsValid()) { FML_LOG(ERROR) << "Could not create Metal context."; diff --git a/impeller/renderer/backend/metal/surface_mtl.h b/impeller/renderer/backend/metal/surface_mtl.h index cebc43e340451..3a7db1c1300d7 100644 --- a/impeller/renderer/backend/metal/surface_mtl.h +++ b/impeller/renderer/backend/metal/surface_mtl.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include "flutter/fml/macros.h" #include "impeller/geometry/rect.h" @@ -37,10 +38,15 @@ class SurfaceMTL final : public Surface { const std::shared_ptr& context, CAMetalLayer* layer); - static std::unique_ptr WrapCurrentMetalLayerDrawable( + static std::unique_ptr MakeFromMetalLayerDrawable( const std::shared_ptr& context, id drawable, std::optional clip_rect = std::nullopt); + + static std::unique_ptr MakeFromTexture( + const std::shared_ptr& context, + id texture, + std::optional clip_rect); #pragma GCC diagnostic pop // |Surface| @@ -58,6 +64,8 @@ class SurfaceMTL final : public Surface { std::weak_ptr context_; std::shared_ptr resolve_texture_; id drawable_ = nil; + std::shared_ptr source_texture_; + std::shared_ptr destination_texture_; bool requires_blit_ = false; std::optional clip_rect_; @@ -67,6 +75,8 @@ class SurfaceMTL final : public Surface { const RenderTarget& target, std::shared_ptr resolve_texture, id drawable, + std::shared_ptr source_texture, + std::shared_ptr destination_texture, bool requires_blit, std::optional clip_rect); diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index 90f70f5347feb..7ff1810d1751f 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -7,6 +7,7 @@ #include "flutter/fml/trace_event.h" #include "flutter/impeller/renderer/command_buffer.h" #include "impeller/base/validation.h" +#include "impeller/core/texture_descriptor.h" #include "impeller/renderer/backend/metal/context_mtl.h" #include "impeller/renderer/backend/metal/formats_mtl.h" #include "impeller/renderer/backend/metal/texture_mtl.h" @@ -39,17 +40,11 @@ return current_drawable; } -std::unique_ptr SurfaceMTL::WrapCurrentMetalLayerDrawable( - const std::shared_ptr& context, - id drawable, +static std::optional WrapTextureWithRenderTarget( + Allocator& allocator, + id texture, + bool requires_blit, std::optional clip_rect) { - bool requires_blit = ShouldPerformPartialRepaint(clip_rect); - const auto color_format = FromMTLPixelFormat(drawable.texture.pixelFormat); - - if (color_format == PixelFormat::kUnknown) { - VALIDATION_LOG << "Unknown drawable color format."; - return nullptr; - } // compositor_context.cc will offset the rendering by the clip origin. Here we // shrink to the size of the clip. This has the same effect as clipping the // rendering but also creates smaller intermediate passes. @@ -57,80 +52,144 @@ if (requires_blit) { if (!clip_rect.has_value()) { VALIDATION_LOG << "Missing clip rectangle."; - return nullptr; + return std::nullopt; } root_size = ISize(clip_rect->size.width, clip_rect->size.height); } else { - root_size = {static_cast(drawable.texture.width), - static_cast(drawable.texture.height)}; + root_size = {static_cast(texture.width), + static_cast(texture.height)}; } - TextureDescriptor msaa_tex_desc; - msaa_tex_desc.storage_mode = StorageMode::kDeviceTransient; - msaa_tex_desc.type = TextureType::kTexture2DMultisample; - msaa_tex_desc.sample_count = SampleCount::kCount4; - msaa_tex_desc.format = color_format; - msaa_tex_desc.size = root_size; - msaa_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); - - auto msaa_tex = context->GetResourceAllocator()->CreateTexture(msaa_tex_desc); - if (!msaa_tex) { - VALIDATION_LOG << "Could not allocate MSAA color texture."; - return nullptr; - } - msaa_tex->SetLabel("ImpellerOnscreenColorMSAA"); - TextureDescriptor resolve_tex_desc; - resolve_tex_desc.format = color_format; - resolve_tex_desc.size = msaa_tex_desc.size; + resolve_tex_desc.format = FromMTLPixelFormat(texture.pixelFormat); + resolve_tex_desc.size = root_size; resolve_tex_desc.usage = static_cast(TextureUsage::kRenderTarget) | static_cast(TextureUsage::kShaderRead); resolve_tex_desc.sample_count = SampleCount::kCount1; resolve_tex_desc.storage_mode = StorageMode::kDevicePrivate; + if (resolve_tex_desc.format == PixelFormat::kUnknown) { + VALIDATION_LOG << "Unknown drawable color format."; + return std::nullopt; + } + // Create color resolve texture. std::shared_ptr resolve_tex; if (requires_blit) { resolve_tex_desc.compression_type = CompressionType::kLossy; - resolve_tex = - context->GetResourceAllocator()->CreateTexture(resolve_tex_desc); + resolve_tex = allocator.CreateTexture(resolve_tex_desc); } else { - resolve_tex = - std::make_shared(resolve_tex_desc, drawable.texture); + resolve_tex = std::make_shared(resolve_tex_desc, texture); } if (!resolve_tex) { VALIDATION_LOG << "Could not wrap resolve texture."; - return nullptr; + return std::nullopt; } resolve_tex->SetLabel("ImpellerOnscreenResolve"); + TextureDescriptor msaa_tex_desc; + msaa_tex_desc.storage_mode = StorageMode::kDeviceTransient; + msaa_tex_desc.type = TextureType::kTexture2DMultisample; + msaa_tex_desc.sample_count = SampleCount::kCount4; + msaa_tex_desc.format = resolve_tex->GetTextureDescriptor().format; + msaa_tex_desc.size = resolve_tex->GetSize(); + msaa_tex_desc.usage = static_cast(TextureUsage::kRenderTarget); + + auto msaa_tex = allocator.CreateTexture(msaa_tex_desc); + if (!msaa_tex) { + VALIDATION_LOG << "Could not allocate MSAA color texture."; + return std::nullopt; + } + msaa_tex->SetLabel("ImpellerOnscreenColorMSAA"); + ColorAttachment color0; color0.texture = msaa_tex; color0.clear_color = Color::DarkSlateGray(); color0.load_action = LoadAction::kClear; color0.store_action = StoreAction::kMultisampleResolve; - color0.resolve_texture = resolve_tex; + color0.resolve_texture = std::move(resolve_tex); RenderTarget render_target_desc; render_target_desc.SetColorAttachment(color0, 0u); - // The constructor is private. So make_unique may not be used. - return std::unique_ptr(new SurfaceMTL(context, render_target_desc, - resolve_tex, drawable, - requires_blit, clip_rect)); + return render_target_desc; +} + +std::unique_ptr SurfaceMTL::MakeFromMetalLayerDrawable( + const std::shared_ptr& context, + id drawable, + std::optional clip_rect) { + bool requires_blit = ShouldPerformPartialRepaint(clip_rect); + + auto render_target = + WrapTextureWithRenderTarget(*context->GetResourceAllocator(), + drawable.texture, requires_blit, clip_rect); + if (!render_target) { + return nullptr; + } + + auto source_texture = + requires_blit ? render_target->GetRenderTargetTexture() : nullptr; + auto destination_texture = TextureMTL::Wrapper( + render_target->GetRenderTargetTexture()->GetTextureDescriptor(), + drawable.texture); + + return std::unique_ptr(new SurfaceMTL( + context, // context + *render_target, // target + render_target->GetRenderTargetTexture(), // resolve_texture + drawable, // drawable + source_texture, // source_texture + destination_texture, // destination_texture + requires_blit, // requires_blit + clip_rect // clip_rect + )); +} + +std::unique_ptr SurfaceMTL::MakeFromTexture( + const std::shared_ptr& context, + id texture, + std::optional clip_rect) { + bool requires_blit = ShouldPerformPartialRepaint(clip_rect); + + auto render_target = WrapTextureWithRenderTarget( + *context->GetResourceAllocator(), texture, requires_blit, clip_rect); + if (!render_target) { + return nullptr; + } + + auto source_texture = + requires_blit ? render_target->GetRenderTargetTexture() : nullptr; + auto destination_texture = TextureMTL::Wrapper( + render_target->GetRenderTargetTexture()->GetTextureDescriptor(), texture); + + return std::unique_ptr(new SurfaceMTL( + context, // context + *render_target, // target + render_target->GetRenderTargetTexture(), // resolve_texture + nil, // drawable + source_texture, // source_texture + destination_texture, // destination_texture + requires_blit, // requires_blit + clip_rect // clip_rect + )); } SurfaceMTL::SurfaceMTL(const std::weak_ptr& context, const RenderTarget& target, std::shared_ptr resolve_texture, id drawable, + std::shared_ptr source_texture, + std::shared_ptr destination_texture, bool requires_blit, std::optional clip_rect) : Surface(target), context_(context), resolve_texture_(std::move(resolve_texture)), drawable_(drawable), + source_texture_(std::move(source_texture)), + destination_texture_(std::move(destination_texture)), requires_blit_(requires_blit), clip_rect_(clip_rect) {} @@ -173,16 +232,16 @@ static bool ShouldWaitForCommandBuffer() { // |Surface| bool SurfaceMTL::Present() const { - if (drawable_ == nil) { - return false; - } - auto context = context_.lock(); if (!context) { return false; } if (requires_blit_) { + if (!(source_texture_ && destination_texture_)) { + return false; + } + auto blit_command_buffer = context->CreateCommandBuffer(); if (!blit_command_buffer) { return false; @@ -192,8 +251,7 @@ static bool ShouldWaitForCommandBuffer() { VALIDATION_LOG << "Missing clip rectangle."; return false; } - auto current = TextureMTL::Wrapper({}, drawable_.texture); - blit_pass->AddCopy(resolve_texture_, current, std::nullopt, + blit_pass->AddCopy(source_texture_, destination_texture_, std::nullopt, clip_rect_->origin); blit_pass->EncodeCommands(context->GetResourceAllocator()); if (!blit_command_buffer->SubmitCommands()) { @@ -201,13 +259,15 @@ static bool ShouldWaitForCommandBuffer() { } } - if (ShouldWaitForCommandBuffer()) { - id command_buffer = - ContextMTL::Cast(context.get())->CreateMTLCommandBuffer(); - [command_buffer commit]; - [command_buffer waitUntilScheduled]; + if (drawable_) { + if (ShouldWaitForCommandBuffer()) { + id command_buffer = + ContextMTL::Cast(context.get())->CreateMTLCommandBuffer(); + [command_buffer commit]; + [command_buffer waitUntilScheduled]; + } + [drawable_ present]; } - [drawable_ present]; return true; } diff --git a/impeller/renderer/backend/metal/texture_mtl.h b/impeller/renderer/backend/metal/texture_mtl.h index 9d9378d1b6ce7..91cd8a122da11 100644 --- a/impeller/renderer/backend/metal/texture_mtl.h +++ b/impeller/renderer/backend/metal/texture_mtl.h @@ -19,8 +19,10 @@ class TextureMTL final : public Texture, id texture, bool wrapped = false); - static std::shared_ptr Wrapper(TextureDescriptor desc, - id texture); + static std::shared_ptr Wrapper( + TextureDescriptor desc, + id texture, + std::function deletion_proc = nullptr); // |Texture| ~TextureMTL() override; diff --git a/impeller/renderer/backend/metal/texture_mtl.mm b/impeller/renderer/backend/metal/texture_mtl.mm index 5c63624c014c6..bc57684363a7d 100644 --- a/impeller/renderer/backend/metal/texture_mtl.mm +++ b/impeller/renderer/backend/metal/texture_mtl.mm @@ -9,6 +9,13 @@ namespace impeller { +std::shared_ptr WrapperMTL(TextureDescriptor desc, + const void* mtl_texture, + std::function deletion_proc) { + return TextureMTL::Wrapper(desc, (__bridge id)mtl_texture, + std::move(deletion_proc)); +} + TextureMTL::TextureMTL(TextureDescriptor p_desc, id texture, bool wrapped) @@ -28,9 +35,18 @@ is_valid_ = true; } -std::shared_ptr TextureMTL::Wrapper(TextureDescriptor desc, - id texture) { - return std::make_shared(desc, texture, true); +std::shared_ptr TextureMTL::Wrapper( + TextureDescriptor desc, + id texture, + std::function deletion_proc) { + if (deletion_proc) { + return std::shared_ptr( + new TextureMTL(desc, texture, true), + [deletion_proc = std::move(deletion_proc)](TextureMTL* t) { + deletion_proc(); + }); + } + return std::shared_ptr(new TextureMTL(desc, texture, true)); } TextureMTL::~TextureMTL() = default; diff --git a/impeller/renderer/backend/metal/texture_wrapper_mtl.h b/impeller/renderer/backend/metal/texture_wrapper_mtl.h new file mode 100644 index 0000000000000..e6fe71f0f22e6 --- /dev/null +++ b/impeller/renderer/backend/metal/texture_wrapper_mtl.h @@ -0,0 +1,16 @@ +// 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. + +#pragma once + +#include "impeller/core/texture.h" + +namespace impeller { + +std::shared_ptr WrapTextureMTL( + TextureDescriptor desc, + const void* mtl_texture, + std::function deletion_proc = nullptr); + +} // namespace impeller diff --git a/impeller/renderer/backend/metal/texture_wrapper_mtl.mm b/impeller/renderer/backend/metal/texture_wrapper_mtl.mm new file mode 100644 index 0000000000000..2b6a908f6d7cb --- /dev/null +++ b/impeller/renderer/backend/metal/texture_wrapper_mtl.mm @@ -0,0 +1,22 @@ +// 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/renderer/backend/metal/texture_wrapper_mtl.h" + +#include + +#include "impeller/renderer/backend/metal/formats_mtl.h" +#include "impeller/renderer/backend/metal/texture_mtl.h" + +namespace impeller { + +std::shared_ptr WrapTextureMTL(TextureDescriptor desc, + const void* mtl_texture, + std::function deletion_proc) { + auto texture = (__bridge id)mtl_texture; + desc.format = FromMTLPixelFormat(texture.pixelFormat); + return TextureMTL::Wrapper(desc, texture, std::move(deletion_proc)); +} + +} // namespace impeller diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 2136c60cdd44e..163e7aa36e131 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -627,8 +627,8 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( if (external_view_embedder_ && (!raster_thread_merger_ || raster_thread_merger_->IsMerged())) { FML_DCHECK(!frame->IsSubmitted()); - external_view_embedder_->SubmitFrame(surface_->GetContext(), - std::move(frame)); + external_view_embedder_->SubmitFrame( + surface_->GetContext(), surface_->GetAiksContext(), std::move(frame)); } else { frame->Submit(); } diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 53de96c86bd4e..daf36364851b1 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -74,8 +74,9 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder { PostPrerollResult( fml::RefPtr raster_thread_merger)); MOCK_METHOD1(CompositeEmbeddedView, DlCanvas*(int64_t view_id)); - MOCK_METHOD2(SubmitFrame, + MOCK_METHOD3(SubmitFrame, void(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame)); MOCK_METHOD2(EndFrame, void(bool should_resubmit_frame, diff --git a/shell/common/shell_test_external_view_embedder.cc b/shell/common/shell_test_external_view_embedder.cc index 2536bb62ac6a2..22b9bfe13554b 100644 --- a/shell/common/shell_test_external_view_embedder.cc +++ b/shell/common/shell_test_external_view_embedder.cc @@ -91,6 +91,7 @@ DlCanvas* ShellTestExternalViewEmbedder::CompositeEmbeddedView( // |ExternalViewEmbedder| void ShellTestExternalViewEmbedder::SubmitFrame( GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) { if (!frame) { return; diff --git a/shell/common/shell_test_external_view_embedder.h b/shell/common/shell_test_external_view_embedder.h index 204472d5bc050..36a392d208856 100644 --- a/shell/common/shell_test_external_view_embedder.h +++ b/shell/common/shell_test_external_view_embedder.h @@ -75,6 +75,7 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder { // |ExternalViewEmbedder| void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override; // |ExternalViewEmbedder| diff --git a/shell/gpu/gpu_surface_metal_impeller.h b/shell/gpu/gpu_surface_metal_impeller.h index 3b139c1890384..d89e5bf208166 100644 --- a/shell/gpu/gpu_surface_metal_impeller.h +++ b/shell/gpu/gpu_surface_metal_impeller.h @@ -5,22 +5,25 @@ #ifndef FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_IMPELLER_H_ #define FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_IMPELLER_H_ -#include +#include #include "flutter/flow/surface.h" #include "flutter/fml/macros.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/impeller/aiks/aiks_context.h" +#include "flutter/impeller/renderer/backend/metal/context_mtl.h" #include "flutter/impeller/renderer/renderer.h" #include "flutter/shell/gpu/gpu_surface_metal_delegate.h" #include "third_party/skia/include/gpu/mtl/GrMtlTypes.h" namespace flutter { -class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalImpeller : public Surface { +class IMPELLER_CA_METAL_LAYER_AVAILABLE GPUSurfaceMetalImpeller + : public Surface { public: GPUSurfaceMetalImpeller(GPUSurfaceMetalDelegate* delegate, - const std::shared_ptr& context); + const std::shared_ptr& context, + bool render_to_surface = true); // |Surface| ~GPUSurfaceMetalImpeller(); @@ -32,16 +35,29 @@ class SK_API_AVAILABLE_CA_METAL_LAYER GPUSurfaceMetalImpeller : public Surface { private: const GPUSurfaceMetalDelegate* delegate_; + const MTLRenderTargetType render_target_type_; std::shared_ptr impeller_renderer_; std::shared_ptr aiks_context_; - fml::scoped_nsprotocol> last_drawable_; + fml::scoped_nsprotocol> last_texture_; + // TODO(38466): Refactor GPU surface APIs take into account the fact that an + // external view embedder may want to render to the root surface. This is a + // hack to make avoid allocating resources for the root surface when an + // external view embedder is present. + bool render_to_surface_ = true; bool disable_partial_repaint_ = false; // Accumulated damage for each framebuffer; Key is address of underlying // MTLTexture for each drawable std::map damage_; // |Surface| - std::unique_ptr AcquireFrame(const SkISize& size) override; + std::unique_ptr AcquireFrame( + const SkISize& frame_size) override; + + std::unique_ptr AcquireFrameFromCAMetalLayer( + const SkISize& frame_size); + + std::unique_ptr AcquireFrameFromMTLTexture( + const SkISize& frame_size); // |Surface| SkMatrix GetRootTransformation() const override; diff --git a/shell/gpu/gpu_surface_metal_impeller.mm b/shell/gpu/gpu_surface_metal_impeller.mm index 94f77a1ec192f..32b2f28325394 100644 --- a/shell/gpu/gpu_surface_metal_impeller.mm +++ b/shell/gpu/gpu_surface_metal_impeller.mm @@ -29,11 +29,14 @@ } GPUSurfaceMetalImpeller::GPUSurfaceMetalImpeller(GPUSurfaceMetalDelegate* delegate, - const std::shared_ptr& context) + const std::shared_ptr& context, + bool render_to_surface) : delegate_(delegate), + render_target_type_(delegate->GetRenderTargetType()), impeller_renderer_(CreateImpellerRenderer(context)), aiks_context_( - std::make_shared(impeller_renderer_ ? context : nullptr)) { + std::make_shared(impeller_renderer_ ? context : nullptr)), + render_to_surface_(render_to_surface) { // If this preference is explicitly set, we allow for disabling partial repaint. NSNumber* disablePartialRepaint = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FLTDisablePartialRepaint"]; @@ -50,7 +53,7 @@ } // |Surface| -std::unique_ptr GPUSurfaceMetalImpeller::AcquireFrame(const SkISize& frame_info) { +std::unique_ptr GPUSurfaceMetalImpeller::AcquireFrame(const SkISize& frame_size) { TRACE_EVENT0("impeller", "GPUSurfaceMetalImpeller::AcquireFrame"); if (!IsValid()) { @@ -58,7 +61,33 @@ return nullptr; } - auto layer = delegate_->GetCAMetalLayer(frame_info); + if (frame_size.isEmpty()) { + FML_LOG(ERROR) << "Metal surface was asked for an empty frame."; + return nullptr; + } + + if (!render_to_surface_) { + return std::make_unique( + nullptr, SurfaceFrame::FramebufferInfo(), + [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { return true; }, frame_size); + } + + switch (render_target_type_) { + case MTLRenderTargetType::kCAMetalLayer: + return AcquireFrameFromCAMetalLayer(frame_size); + case MTLRenderTargetType::kMTLTexture: + return AcquireFrameFromMTLTexture(frame_size); + default: + FML_CHECK(false) << "Unknown MTLRenderTargetType type."; + } + + return nullptr; +} + +std::unique_ptr GPUSurfaceMetalImpeller::AcquireFrameFromCAMetalLayer( + const SkISize& frame_size) { + auto layer = delegate_->GetCAMetalLayer(frame_size); + if (!layer) { FML_LOG(ERROR) << "Invalid CAMetalLayer given by the embedder."; return nullptr; @@ -69,15 +98,16 @@ auto drawable = impeller::SurfaceMTL::GetMetalDrawableAndValidate( impeller_renderer_->GetContext(), mtl_layer); if (Settings::kSurfaceDataAccessible) { - last_drawable_.reset([drawable retain]); + last_texture_.reset([drawable.texture retain]); } - id metal_drawable = static_cast>(last_drawable_); + id last_texture = static_cast>(last_texture_); SurfaceFrame::SubmitCallback submit_callback = fml::MakeCopyable([this, // renderer = impeller_renderer_, // aiks_context = aiks_context_, // - metal_drawable // + drawable, // + last_texture // ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool { if (!aiks_context) { return false; @@ -90,7 +120,7 @@ } if (!disable_partial_repaint_) { - uintptr_t texture = reinterpret_cast(metal_drawable.texture); + uintptr_t texture = reinterpret_cast(last_texture); for (auto& entry : damage_) { if (entry.first != texture) { @@ -111,8 +141,106 @@ buffer_damage->width(), buffer_damage->height()); } - auto surface = impeller::SurfaceMTL::WrapCurrentMetalLayerDrawable( - impeller_renderer_->GetContext(), metal_drawable, clip_rect); + auto surface = impeller::SurfaceMTL::MakeFromMetalLayerDrawable( + impeller_renderer_->GetContext(), drawable, clip_rect); + + if (clip_rect && (clip_rect->size.width == 0 || clip_rect->size.height == 0)) { + return surface->Present(); + } + + impeller::IRect cull_rect = surface->coverage(); + SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.size.width, cull_rect.size.height); + impeller::DlDispatcher impeller_dispatcher(cull_rect); + display_list->Dispatch(impeller_dispatcher, sk_cull_rect); + auto picture = impeller_dispatcher.EndRecordingAsPicture(); + + return renderer->Render( + std::move(surface), + fml::MakeCopyable([aiks_context, picture = std::move(picture)]( + impeller::RenderTarget& render_target) -> bool { + return aiks_context->Render(picture, render_target); + })); + }); + + SurfaceFrame::FramebufferInfo framebuffer_info; + framebuffer_info.supports_readback = true; + + if (!disable_partial_repaint_) { + // Provide accumulated damage to rasterizer (area in current framebuffer that lags behind + // front buffer) + uintptr_t texture = reinterpret_cast(drawable.texture); + auto i = damage_.find(texture); + if (i != damage_.end()) { + framebuffer_info.existing_damage = i->second; + } + framebuffer_info.supports_partial_repaint = true; + } + + return std::make_unique(nullptr, // surface + framebuffer_info, // framebuffer info + submit_callback, // submit callback + frame_size, // frame size + nullptr, // context result + true // display list fallback + ); +} + +std::unique_ptr GPUSurfaceMetalImpeller::AcquireFrameFromMTLTexture( + const SkISize& frame_size) { + GPUMTLTextureInfo texture_info = delegate_->GetMTLTexture(frame_size); + id mtl_texture = (id)(texture_info.texture); + + if (!mtl_texture) { + FML_LOG(ERROR) << "Invalid MTLTexture given by the embedder."; + return nullptr; + } + + if (Settings::kSurfaceDataAccessible) { + last_texture_.reset([mtl_texture retain]); + } + + SurfaceFrame::SubmitCallback submit_callback = + fml::MakeCopyable([this, // + renderer = impeller_renderer_, // + aiks_context = aiks_context_, // + texture_info, // + mtl_texture, // + delegate = delegate_ // + ](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool { + if (!aiks_context) { + return false; + } + + auto display_list = surface_frame.BuildDisplayList(); + if (!display_list) { + FML_LOG(ERROR) << "Could not build display list for surface frame."; + return false; + } + + if (!disable_partial_repaint_) { + uintptr_t texture_ptr = reinterpret_cast(mtl_texture); + + for (auto& entry : damage_) { + if (entry.first != texture_ptr) { + // Accumulate damage for other framebuffers + if (surface_frame.submit_info().frame_damage) { + entry.second.join(*surface_frame.submit_info().frame_damage); + } + } + } + // Reset accumulated damage for current framebuffer + damage_[texture_ptr] = SkIRect::MakeEmpty(); + } + + std::optional clip_rect; + if (surface_frame.submit_info().buffer_damage.has_value()) { + auto buffer_damage = surface_frame.submit_info().buffer_damage; + clip_rect = impeller::IRect::MakeXYWH(buffer_damage->x(), buffer_damage->y(), + buffer_damage->width(), buffer_damage->height()); + } + + auto surface = + impeller::SurfaceMTL::MakeFromTexture(renderer->GetContext(), mtl_texture, clip_rect); if (clip_rect && (clip_rect->size.width == 0 || clip_rect->size.height == 0)) { return surface->Present(); @@ -130,6 +258,8 @@ impeller::RenderTarget& render_target) -> bool { return aiks_context->Render(picture, render_target); })); + + delegate->PresentTexture(texture_info); }); SurfaceFrame::FramebufferInfo framebuffer_info; @@ -138,7 +268,7 @@ if (!disable_partial_repaint_) { // Provide accumulated damage to rasterizer (area in current framebuffer that lags behind // front buffer) - uintptr_t texture = reinterpret_cast(metal_drawable.texture); + uintptr_t texture = reinterpret_cast(mtl_texture); auto i = damage_.find(texture); if (i != damage_.end()) { framebuffer_info.existing_damage = i->second; @@ -149,7 +279,7 @@ return std::make_unique(nullptr, // surface framebuffer_info, // framebuffer info submit_callback, // submit callback - frame_info, // frame size + frame_size, // frame size nullptr, // context result true // display list fallback ); @@ -188,11 +318,10 @@ } Surface::SurfaceData GPUSurfaceMetalImpeller::GetSurfaceData() const { - if (!(last_drawable_ && [last_drawable_ conformsToProtocol:@protocol(CAMetalDrawable)])) { + if (!(last_texture_ && [last_texture_ conformsToProtocol:@protocol(MTLTexture)])) { return {}; } - id metal_drawable = static_cast>(last_drawable_); - id texture = metal_drawable.texture; + id texture = last_texture_.get(); int bytesPerPixel = 0; std::string pixel_format; switch (texture.pixelFormat) { diff --git a/shell/platform/android/external_view_embedder/external_view_embedder.cc b/shell/platform/android/external_view_embedder/external_view_embedder.cc index f1d8af9f6a710..d29a80eb16a8c 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder.cc @@ -64,6 +64,7 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int64_t view_id) const { // |ExternalViewEmbedder| void AndroidExternalViewEmbedder::SubmitFrame( GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) { TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame"); diff --git a/shell/platform/android/external_view_embedder/external_view_embedder.h b/shell/platform/android/external_view_embedder/external_view_embedder.h index 03bae5ecb8e1a..33b876674f6c3 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder.h +++ b/shell/platform/android/external_view_embedder/external_view_embedder.h @@ -46,6 +46,7 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder { // |ExternalViewEmbedder| void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override; // |ExternalViewEmbedder| diff --git a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc index 3c08eef409281..e6417a08f0800 100644 --- a/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc +++ b/shell/platform/android/external_view_embedder/external_view_embedder_unittests.cc @@ -313,7 +313,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); // Submits frame if no Android view in the current frame. EXPECT_TRUE(did_submit_frame); // Doesn't resubmit frame. @@ -381,7 +381,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); // Doesn't submit frame if there aren't Android views in the previous frame. EXPECT_FALSE(did_submit_frame); // Resubmits frame. @@ -446,7 +446,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrame) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); // Submits frame if there are Android views in the previous frame. EXPECT_TRUE(did_submit_frame); // Doesn't resubmit frame. @@ -553,7 +553,7 @@ TEST(AndroidExternalViewEmbedder, OverlayCoverTwoPlatformViews) { }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); @@ -656,7 +656,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFrameOverlayComposition) { }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); @@ -724,7 +724,7 @@ TEST(AndroidExternalViewEmbedder, SubmitFramePlatformViewWithoutAnyOverlay) { }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); @@ -825,7 +825,7 @@ TEST(AndroidExternalViewEmbedder, DestroyOverlayLayersOnSizeChange) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); @@ -912,7 +912,7 @@ TEST(AndroidExternalViewEmbedder, DoesNotDestroyOverlayLayersOnSizeChange) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); EXPECT_CALL(*jni_mock, FlutterViewEndFrame()); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); @@ -1023,7 +1023,7 @@ TEST(AndroidExternalViewEmbedder, Teardown) { SkSurfaces::Null(1000, 1000), framebuffer_info, [](const SurfaceFrame& surface_frame, DlCanvas* canvas) { return true; }, /*frame_size=*/SkISize::Make(800, 600)); - embedder->SubmitFrame(gr_context.get(), std::move(surface_frame)); + embedder->SubmitFrame(gr_context.get(), nullptr, std::move(surface_frame)); embedder->EndFrame(/*should_resubmit_frame=*/false, raster_thread_merger); diff --git a/shell/platform/darwin/ios/ios_external_view_embedder.h b/shell/platform/darwin/ios/ios_external_view_embedder.h index 3893ccec0c1ab..d83b435930f21 100644 --- a/shell/platform/darwin/ios/ios_external_view_embedder.h +++ b/shell/platform/darwin/ios/ios_external_view_embedder.h @@ -51,6 +51,7 @@ class IOSExternalViewEmbedder : public ExternalViewEmbedder { // |ExternalViewEmbedder| void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override; // |ExternalViewEmbedder| diff --git a/shell/platform/darwin/ios/ios_external_view_embedder.mm b/shell/platform/darwin/ios/ios_external_view_embedder.mm index 4e28b6cfcca82..67112e999d13d 100644 --- a/shell/platform/darwin/ios/ios_external_view_embedder.mm +++ b/shell/platform/darwin/ios/ios_external_view_embedder.mm @@ -66,8 +66,10 @@ } // |ExternalViewEmbedder| -void IOSExternalViewEmbedder::SubmitFrame(GrDirectContext* context, - std::unique_ptr frame) { +void IOSExternalViewEmbedder::SubmitFrame( + GrDirectContext* context, + const std::shared_ptr& aiks_context, + std::unique_ptr frame) { TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::SubmitFrame"); FML_CHECK(platform_views_controller_); platform_views_controller_->SubmitFrame(context, ios_context_, std::move(frame)); diff --git a/shell/platform/embedder/BUILD.gn b/shell/platform/embedder/BUILD.gn index 9c827ac38bd3c..aa43f3f48b755 100644 --- a/shell/platform/embedder/BUILD.gn +++ b/shell/platform/embedder/BUILD.gn @@ -5,6 +5,7 @@ import("//build/toolchain/clang.gni") import("//flutter/build/zip_bundle.gni") import("//flutter/common/config.gni") +import("//flutter/impeller/tools/impeller.gni") import("//flutter/shell/gpu/gpu.gni") import("//flutter/shell/platform/embedder/embedder.gni") import("//flutter/testing/testing.gni") @@ -75,6 +76,8 @@ template("embedder_source_set") { "embedder_render_target.h", "embedder_render_target_cache.cc", "embedder_render_target_cache.h", + "embedder_render_target_skia.cc", + "embedder_render_target_skia.h", "embedder_struct_macros.h", "embedder_surface.cc", "embedder_surface.h", @@ -91,6 +94,8 @@ template("embedder_source_set") { "vsync_waiter_embedder.h", ] + public_deps = [ ":embedder_headers" ] + if (embedder_enable_gl) { sources += [ "embedder_external_texture_gl.cc", @@ -116,6 +121,15 @@ template("embedder_source_set") { "//third_party/skia", ] + if (impeller_supports_rendering) { + sources += [ + "embedder_render_target_impeller.cc", + "embedder_render_target_impeller.h", + ] + + deps += [ "//flutter/impeller" ] + } + if (embedder_enable_metal) { sources += [ "embedder_external_texture_metal.h", @@ -124,6 +138,13 @@ template("embedder_source_set") { "embedder_surface_metal.mm", ] + if (impeller_supports_rendering) { + sources += [ + "embedder_surface_metal_impeller.h", + "embedder_surface_metal_impeller.mm", + ] + } + cflags_objc = flutter_cflags_objc cflags_objcc = flutter_cflags_objcc @@ -142,12 +163,11 @@ template("embedder_source_set") { ] } - public_deps = [ ":embedder_headers" ] - public_configs += [ ":embedder_gpu_configuration_config", ":embedder_header_config", "//flutter:config", + "//flutter/impeller:impeller_public_config", ] } } diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 17df21bf1f6a2..b6db264a486af 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -55,6 +55,7 @@ extern const intptr_t kPlatformStrongDillSize; #include "flutter/shell/platform/embedder/embedder_external_texture_resolver.h" #include "flutter/shell/platform/embedder/embedder_platform_message_response.h" #include "flutter/shell/platform/embedder/embedder_render_target.h" +#include "flutter/shell/platform/embedder/embedder_render_target_skia.h" #include "flutter/shell/platform/embedder/embedder_struct_macros.h" #include "flutter/shell/platform/embedder/embedder_task_runner.h" #include "flutter/shell/platform/embedder/embedder_thread_host.h" @@ -70,7 +71,14 @@ extern const intptr_t kPlatformStrongDillSize; #ifdef SHELL_ENABLE_METAL #include "flutter/shell/platform/embedder/embedder_surface_metal.h" #include "third_party/skia/include/ports/SkCFObject.h" -#endif +#ifdef IMPELLER_SUPPORTS_RENDERING +#include "flutter/shell/platform/embedder/embedder_render_target_impeller.h" // nogncheck +#include "flutter/shell/platform/embedder/embedder_surface_metal_impeller.h" // nogncheck +#include "impeller/core/texture.h" // nogncheck +#include "impeller/renderer/backend/metal/texture_wrapper_mtl.h" // nogncheck +#include "impeller/renderer/render_target.h" // nogncheck +#endif // IMPELLER_SUPPORTS_RENDERING +#endif // SHELL_ENABLE_METAL const int32_t kFlutterSemanticsNodeIdBatchEnd = -1; const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1; @@ -454,7 +462,8 @@ InferMetalPlatformViewCreationCallback( const flutter::PlatformViewEmbedder::PlatformDispatchTable& platform_dispatch_table, std::unique_ptr - external_view_embedder) { + external_view_embedder, + bool enable_impeller) { if (config->type != kMetal) { return nullptr; } @@ -488,20 +497,33 @@ InferMetalPlatformViewCreationCallback( return texture_info; }; - flutter::EmbedderSurfaceMetal::MetalDispatchTable metal_dispatch_table = { - .present = metal_present, - .get_texture = metal_get_texture, - }; - std::shared_ptr view_embedder = std::move(external_view_embedder); - std::unique_ptr embedder_surface = - std::make_unique( - const_cast(config->metal.device), - const_cast( - config->metal.present_command_queue), - metal_dispatch_table, view_embedder); + std::unique_ptr embedder_surface; + + if (enable_impeller) { + flutter::EmbedderSurfaceMetalImpeller::MetalDispatchTable + metal_dispatch_table = { + .present = metal_present, + .get_texture = metal_get_texture, + }; + embedder_surface = std::make_unique( + const_cast(config->metal.device), + const_cast( + config->metal.present_command_queue), + metal_dispatch_table, view_embedder); + } else { + flutter::EmbedderSurfaceMetal::MetalDispatchTable metal_dispatch_table = { + .present = metal_present, + .get_texture = metal_get_texture, + }; + embedder_surface = std::make_unique( + const_cast(config->metal.device), + const_cast( + config->metal.present_command_queue), + metal_dispatch_table, view_embedder); + } // The static leak checker gets confused by the use of fml::MakeCopyable. // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) @@ -652,7 +674,8 @@ InferPlatformViewCreationCallback( const flutter::PlatformViewEmbedder::PlatformDispatchTable& platform_dispatch_table, std::unique_ptr - external_view_embedder) { + external_view_embedder, + bool enable_impeller) { if (config == nullptr) { return nullptr; } @@ -669,7 +692,7 @@ InferPlatformViewCreationCallback( case kMetal: return InferMetalPlatformViewCreationCallback( config, user_data, platform_dispatch_table, - std::move(external_view_embedder)); + std::move(external_view_embedder), enable_impeller); case kVulkan: return InferVulkanPlatformViewCreationCallback( config, user_data, platform_dispatch_table, @@ -899,6 +922,76 @@ static sk_sp MakeSkSurfaceFromBackingStore( #endif } +static std::unique_ptr +MakeRenderTargetFromBackingStoreImpeller( + FlutterBackingStore backing_store, + const fml::closure& on_release, + const std::shared_ptr& aiks_context, + const FlutterBackingStoreConfig& config, + const FlutterMetalBackingStore* metal) { +#if defined(SHELL_ENABLE_METAL) && defined(IMPELLER_SUPPORTS_RENDERING) + if (!metal->texture.texture) { + FML_LOG(ERROR) << "Embedder supplied null Metal texture."; + return nullptr; + } + + const auto size = impeller::ISize(config.size.width, config.size.height); + + impeller::TextureDescriptor resolve_tex_desc; + resolve_tex_desc.size = size; + resolve_tex_desc.sample_count = impeller::SampleCount::kCount1; + resolve_tex_desc.storage_mode = impeller::StorageMode::kDevicePrivate; + resolve_tex_desc.usage = + static_cast(impeller::TextureUsage::kRenderTarget) | + static_cast(impeller::TextureUsage::kShaderRead); + + auto resolve_tex = impeller::WrapTextureMTL( + resolve_tex_desc, metal->texture.texture, + [callback = metal->texture.destruction_callback, + user_data = metal->texture.user_data]() { callback(user_data); }); + if (!resolve_tex) { + FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture."; + return nullptr; + } + resolve_tex->SetLabel("ImpellerBackingStoreResolve"); + + impeller::TextureDescriptor msaa_tex_desc; + msaa_tex_desc.storage_mode = impeller::StorageMode::kDeviceTransient; + msaa_tex_desc.type = impeller::TextureType::kTexture2DMultisample; + msaa_tex_desc.sample_count = impeller::SampleCount::kCount4; + msaa_tex_desc.format = resolve_tex->GetTextureDescriptor().format; + msaa_tex_desc.size = size; + msaa_tex_desc.usage = + static_cast(impeller::TextureUsage::kRenderTarget); + + auto msaa_tex = + aiks_context->GetContext()->GetResourceAllocator()->CreateTexture( + msaa_tex_desc); + if (!msaa_tex) { + FML_LOG(ERROR) << "Could not allocate MSAA color texture."; + return nullptr; + } + msaa_tex->SetLabel("ImpellerBackingStoreColorMSAA"); + + impeller::ColorAttachment color0; + color0.texture = msaa_tex; + color0.clear_color = impeller::Color::DarkSlateGray(); + color0.load_action = impeller::LoadAction::kClear; + color0.store_action = impeller::StoreAction::kMultisampleResolve; + color0.resolve_texture = resolve_tex; + + impeller::RenderTarget render_target_desc; + render_target_desc.SetColorAttachment(color0, 0u); + + return std::make_unique( + backing_store, aiks_context, + std::make_unique(std::move(render_target_desc)), + on_release); +#else + return nullptr; +#endif +} + static sk_sp MakeSkSurfaceFromBackingStore( GrDirectContext* context, const FlutterBackingStoreConfig& config, @@ -953,9 +1046,23 @@ static sk_sp MakeSkSurfaceFromBackingStore( } static std::unique_ptr -CreateEmbedderRenderTarget(const FlutterCompositor* compositor, - const FlutterBackingStoreConfig& config, - GrDirectContext* context) { +MakeRenderTargetFromSkSurface(FlutterBackingStore backing_store, + sk_sp skia_surface, + fml::closure on_release) { + if (!skia_surface) { + return nullptr; + } + return std::make_unique( + backing_store, std::move(skia_surface), std::move(on_release)); +} + +static std::unique_ptr +CreateEmbedderRenderTarget( + const FlutterCompositor* compositor, + const FlutterBackingStoreConfig& config, + GrDirectContext* context, + const std::shared_ptr& aiks_context, + bool enable_impeller) { FlutterBackingStore backing_store = {}; backing_store.struct_size = sizeof(backing_store); @@ -990,53 +1097,77 @@ CreateEmbedderRenderTarget(const FlutterCompositor* compositor, // No safe access checks on the renderer are necessary since we allocated // the struct. - sk_sp render_surface; + std::unique_ptr render_target; switch (backing_store.type) { - case kFlutterBackingStoreTypeOpenGL: + case kFlutterBackingStoreTypeOpenGL: { switch (backing_store.open_gl.type) { - case kFlutterOpenGLTargetTypeTexture: - render_surface = MakeSkSurfaceFromBackingStore( + case kFlutterOpenGLTargetTypeTexture: { + auto skia_surface = MakeSkSurfaceFromBackingStore( context, config, &backing_store.open_gl.texture); + render_target = MakeRenderTargetFromSkSurface( + backing_store, std::move(skia_surface), + collect_callback.Release()); break; - case kFlutterOpenGLTargetTypeFramebuffer: - render_surface = MakeSkSurfaceFromBackingStore( + } + case kFlutterOpenGLTargetTypeFramebuffer: { + auto skia_surface = MakeSkSurfaceFromBackingStore( context, config, &backing_store.open_gl.framebuffer); + render_target = MakeRenderTargetFromSkSurface( + backing_store, std::move(skia_surface), + collect_callback.Release()); break; + } } break; - case kFlutterBackingStoreTypeSoftware: - render_surface = MakeSkSurfaceFromBackingStore(context, config, - &backing_store.software); + } + case kFlutterBackingStoreTypeSoftware: { + auto skia_surface = MakeSkSurfaceFromBackingStore( + context, config, &backing_store.software); + render_target = MakeRenderTargetFromSkSurface( + backing_store, std::move(skia_surface), collect_callback.Release()); break; - case kFlutterBackingStoreTypeSoftware2: - render_surface = MakeSkSurfaceFromBackingStore(context, config, - &backing_store.software2); + } + case kFlutterBackingStoreTypeSoftware2: { + auto skia_surface = MakeSkSurfaceFromBackingStore( + context, config, &backing_store.software2); + render_target = MakeRenderTargetFromSkSurface( + backing_store, std::move(skia_surface), collect_callback.Release()); break; - case kFlutterBackingStoreTypeMetal: - render_surface = - MakeSkSurfaceFromBackingStore(context, config, &backing_store.metal); + } + case kFlutterBackingStoreTypeMetal: { + if (enable_impeller) { + auto impeller_target = MakeRenderTargetFromBackingStoreImpeller( + backing_store, collect_callback.Release(), aiks_context, config, + &backing_store.metal); + } else { + auto skia_surface = MakeSkSurfaceFromBackingStore(context, config, + &backing_store.metal); + render_target = MakeRenderTargetFromSkSurface( + backing_store, std::move(skia_surface), collect_callback.Release()); + } break; - - case kFlutterBackingStoreTypeVulkan: - render_surface = + } + case kFlutterBackingStoreTypeVulkan: { + auto skia_surface = MakeSkSurfaceFromBackingStore(context, config, &backing_store.vulkan); + render_target = MakeRenderTargetFromSkSurface( + backing_store, std::move(skia_surface), collect_callback.Release()); break; + } }; - if (!render_surface) { + if (!render_target) { FML_LOG(ERROR) << "Could not create a surface from an embedder provided " "render target."; - return nullptr; } - - return std::make_unique( - backing_store, std::move(render_surface), collect_callback.Release()); + return render_target; } static std::pair, bool /* halt engine launch if true */> -InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) { +InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor, + bool enable_impeller) { if (compositor == nullptr) { return {nullptr, false}; } @@ -1060,9 +1191,13 @@ InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) { flutter::EmbedderExternalViewEmbedder::CreateRenderTargetCallback create_render_target_callback = - [captured_compositor](GrDirectContext* context, const auto& config) { + [captured_compositor, enable_impeller]( + GrDirectContext* context, + const std::shared_ptr& aiks_context, + const auto& config) { return CreateEmbedderRenderTarget(&captured_compositor, config, - context); + context, aiks_context, + enable_impeller); }; flutter::EmbedderExternalViewEmbedder::PresentCallback present_callback = @@ -1814,8 +1949,8 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, user_data]() { return ptr(user_data); }; } - auto external_view_embedder_result = - InferExternalViewEmbedderFromArgs(SAFE_ACCESS(args, compositor, nullptr)); + auto external_view_embedder_result = InferExternalViewEmbedderFromArgs( + SAFE_ACCESS(args, compositor, nullptr), settings.enable_impeller); if (external_view_embedder_result.second) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Compositor arguments were invalid."); @@ -1832,7 +1967,7 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, auto on_create_platform_view = InferPlatformViewCreationCallback( config, user_data, platform_dispatch_table, - std::move(external_view_embedder_result.first)); + std::move(external_view_embedder_result.first), settings.enable_impeller); if (!on_create_platform_view) { return LOG_EMBEDDER_ERROR( diff --git a/shell/platform/embedder/embedder_external_view.cc b/shell/platform/embedder/embedder_external_view.cc index cd72a3e4978b6..fe013ef312f8b 100644 --- a/shell/platform/embedder/embedder_external_view.cc +++ b/shell/platform/embedder/embedder_external_view.cc @@ -3,9 +3,15 @@ // found in the LICENSE file. #include "flutter/shell/platform/embedder/embedder_external_view.h" + +#include "flutter/display_list/dl_builder.h" #include "flutter/fml/trace_event.h" #include "flutter/shell/common/dl_op_spy.h" +#ifdef IMPELLER_SUPPORTS_RENDERING +#include "impeller/display_list/dl_dispatcher.h" +#endif // IMPELLER_SUPPORTS_RENDERING + namespace flutter { static SkISize TransformedSurfaceSize(const SkISize& size, @@ -83,15 +89,30 @@ bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target) { << "Unnecessarily asked to render into a render target when there was " "nothing to render."; - auto surface = render_target.GetRenderSurface(); - if (!surface) { +#ifdef IMPELLER_SUPPORTS_RENDERING + auto* impeller_target = render_target.GetImpellerRenderTarget(); + if (impeller_target) { + auto aiks_context = render_target.GetAiksContext(); + + auto dl_builder = DisplayListBuilder(); + dl_builder.SetTransform(&surface_transformation_); + slice_->render_into(&dl_builder); + + auto dispatcher = impeller::DlDispatcher(); + dispatcher.drawDisplayList(dl_builder.Build(), 1); + return aiks_context->Render(dispatcher.EndRecordingAsPicture(), + *impeller_target); + } +#endif // IMPELLER_SUPPORTS_RENDERING + + auto skia_surface = render_target.GetSkiaSurface(); + if (!skia_surface) { return false; } - FML_DCHECK(SkISize::Make(surface->width(), surface->height()) == - render_surface_size_); + FML_DCHECK(render_target.GetRenderTargetSize() == render_surface_size_); - auto canvas = surface->getCanvas(); + auto canvas = skia_surface->getCanvas(); if (!canvas) { return false; } diff --git a/shell/platform/embedder/embedder_external_view_embedder.cc b/shell/platform/embedder/embedder_external_view_embedder.cc index e4870090c6c9f..f87d451a6af26 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.cc +++ b/shell/platform/embedder/embedder_external_view_embedder.cc @@ -125,6 +125,7 @@ static FlutterBackingStoreConfig MakeBackingStoreConfig( // |ExternalViewEmbedder| void EmbedderExternalViewEmbedder::SubmitFrame( GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) { auto [matched_render_targets, pending_keys] = render_target_cache_.GetExistingTargetsInCache(pending_views_); @@ -172,8 +173,8 @@ void EmbedderExternalViewEmbedder::SubmitFrame( // the context must be reset. // // @warning: Embedder may trample on our OpenGL context here. - auto render_target = - create_render_target_callback_(context, backing_store_config); + auto render_target = create_render_target_callback_(context, aiks_context, + backing_store_config); if (!render_target) { FML_LOG(ERROR) << "Embedder did not return a valid render target."; diff --git a/shell/platform/embedder/embedder_external_view_embedder.h b/shell/platform/embedder/embedder_external_view_embedder.h index 55a08f0627a72..014f7393c416e 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.h +++ b/shell/platform/embedder/embedder_external_view_embedder.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_VIEW_EMBEDDER_H_ #include +#include #include #include "flutter/flow/embedded_views.h" @@ -31,6 +32,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { using CreateRenderTargetCallback = std::function( GrDirectContext* context, + const std::shared_ptr& aiks_context, const FlutterBackingStoreConfig& config)>; using PresentCallback = std::function& layers)>; @@ -95,6 +97,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { // |ExternalViewEmbedder| void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override; // |ExternalViewEmbedder| diff --git a/shell/platform/embedder/embedder_render_target.cc b/shell/platform/embedder/embedder_render_target.cc index 5d6d22887c043..69259e3ab206d 100644 --- a/shell/platform/embedder/embedder_render_target.cc +++ b/shell/platform/embedder/embedder_render_target.cc @@ -4,24 +4,17 @@ #include "flutter/shell/platform/embedder/embedder_render_target.h" +#include #include -#include "flutter/fml/logging.h" - -#include "third_party/skia/include/core/SkSurface.h" - namespace flutter { EmbedderRenderTarget::EmbedderRenderTarget(FlutterBackingStore backing_store, - sk_sp render_surface, fml::closure on_release) - : backing_store_(backing_store), - render_surface_(std::move(render_surface)), - on_release_(std::move(on_release)) { + : backing_store_(backing_store), on_release_(std::move(on_release)) { // TODO(38468): The optimization to elide backing store updates between frames // has not been implemented yet. backing_store_.did_update = true; - FML_DCHECK(render_surface_); } EmbedderRenderTarget::~EmbedderRenderTarget() { @@ -34,8 +27,4 @@ const FlutterBackingStore* EmbedderRenderTarget::GetBackingStore() const { return &backing_store_; } -sk_sp EmbedderRenderTarget::GetRenderSurface() const { - return render_surface_; -} - } // namespace flutter diff --git a/shell/platform/embedder/embedder_render_target.h b/shell/platform/embedder/embedder_render_target.h index 8afbed31e30f0..cfbb67c07f5f3 100644 --- a/shell/platform/embedder/embedder_render_target.h +++ b/shell/platform/embedder/embedder_render_target.h @@ -5,12 +5,18 @@ #ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_H_ #define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_H_ +#include #include "flutter/fml/closure.h" #include "flutter/fml/macros.h" #include "flutter/shell/platform/embedder/embedder.h" -#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkSize.h" #include "third_party/skia/include/core/SkSurface.h" +namespace impeller { +class RenderTarget; +class AiksContext; +} // namespace impeller + namespace flutter { //------------------------------------------------------------------------------ @@ -21,29 +27,12 @@ namespace flutter { /// class EmbedderRenderTarget { public: - //---------------------------------------------------------------------------- - /// @brief Creates a render target whose backing store is managed by the - /// embedder. The way this render target is exposed to the engine - /// is via an SkSurface and a callback that is invoked by this - /// object in its destructor. - /// - /// @param[in] backing_store The backing store describing this render - /// target. - /// @param[in] render_surface The surface for this target. - /// @param[in] on_release The callback to invoke (eventually forwarded - /// to the embedder) when the backing store is no - /// longer required by the engine. - /// - EmbedderRenderTarget(FlutterBackingStore backing_store, - sk_sp render_surface, - fml::closure on_release); - //---------------------------------------------------------------------------- /// @brief Destroys this instance of the render target and invokes the /// callback for the embedder to release its resource associated /// with the particular backing store. /// - ~EmbedderRenderTarget(); + virtual ~EmbedderRenderTarget(); //---------------------------------------------------------------------------- /// @brief A render surface the rasterizer can use to draw into the @@ -51,7 +40,30 @@ class EmbedderRenderTarget { /// /// @return The render surface. /// - sk_sp GetRenderSurface() const; + virtual sk_sp GetSkiaSurface() const = 0; + + //---------------------------------------------------------------------------- + /// @brief An impeller render target the rasterizer can use to draw into + /// the backing store. + /// + /// @return The Impeller render target. + /// + virtual impeller::RenderTarget* GetImpellerRenderTarget() const = 0; + + //---------------------------------------------------------------------------- + /// @brief Returns the AiksContext that should be used for rendering, if + /// this render target is backed by Impeller. + /// + /// @return The Impeller Aiks context. + /// + virtual std::shared_ptr GetAiksContext() const = 0; + + //---------------------------------------------------------------------------- + /// @brief Returns the size of the render target. + /// + /// @return The size of the render target. + /// + virtual SkISize GetRenderTargetSize() const = 0; //---------------------------------------------------------------------------- /// @brief The embedder backing store descriptor. This is the descriptor @@ -65,9 +77,25 @@ class EmbedderRenderTarget { /// const FlutterBackingStore* GetBackingStore() const; + protected: + //---------------------------------------------------------------------------- + /// @brief Creates a render target whose backing store is managed by the + /// embedder. The way this render target is exposed to the engine + /// is via an SkSurface and a callback that is invoked by this + /// object in its destructor. + /// + /// @param[in] backing_store The backing store describing this render + /// target. + /// @param[in] on_release The callback to invoke (eventually forwarded + /// to the embedder) when the backing store is no + /// longer required by the engine. + /// + EmbedderRenderTarget(FlutterBackingStore backing_store, + fml::closure on_release); + private: FlutterBackingStore backing_store_; - sk_sp render_surface_; + fml::closure on_release_; FML_DISALLOW_COPY_AND_ASSIGN(EmbedderRenderTarget); diff --git a/shell/platform/embedder/embedder_render_target_cache.cc b/shell/platform/embedder/embedder_render_target_cache.cc index 1347b032791d1..3d0e6b4c99858 100644 --- a/shell/platform/embedder/embedder_render_target_cache.cc +++ b/shell/platform/embedder/embedder_render_target_cache.cc @@ -56,9 +56,8 @@ void EmbedderRenderTargetCache::CacheRenderTarget( if (target == nullptr) { return; } - auto surface = target->GetRenderSurface(); auto desc = EmbedderExternalView::RenderTargetDescriptor{ - view_identifier, SkISize::Make(surface->width(), surface->height())}; + view_identifier, target->GetRenderTargetSize()}; cached_render_targets_[desc].push(std::move(target)); } diff --git a/shell/platform/embedder/embedder_render_target_impeller.cc b/shell/platform/embedder/embedder_render_target_impeller.cc new file mode 100644 index 0000000000000..44f23b62654d2 --- /dev/null +++ b/shell/platform/embedder/embedder_render_target_impeller.cc @@ -0,0 +1,45 @@ +// 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 "flutter/shell/platform/embedder/embedder_render_target_impeller.h" + +#include "flutter/fml/logging.h" +#include "flutter/impeller/renderer/render_target.h" + +namespace flutter { + +EmbedderRenderTargetImpeller::EmbedderRenderTargetImpeller( + FlutterBackingStore backing_store, + std::shared_ptr aiks_context, + std::unique_ptr impeller_target, + fml::closure on_release) + : EmbedderRenderTarget(backing_store, std::move(on_release)), + aiks_context_(std::move(aiks_context)), + impeller_target_(std::move(impeller_target)) { + FML_DCHECK(aiks_context_); + FML_DCHECK(impeller_target_); +} + +EmbedderRenderTargetImpeller::~EmbedderRenderTargetImpeller() = default; + +sk_sp EmbedderRenderTargetImpeller::GetSkiaSurface() const { + return nullptr; +} + +impeller::RenderTarget* EmbedderRenderTargetImpeller::GetImpellerRenderTarget() + const { + return impeller_target_.get(); +} + +std::shared_ptr +EmbedderRenderTargetImpeller::GetAiksContext() const { + return aiks_context_; +} + +SkISize EmbedderRenderTargetImpeller::GetRenderTargetSize() const { + auto size = impeller_target_->GetRenderTargetSize(); + return SkISize::Make(size.width, size.height); +} + +} // namespace flutter diff --git a/shell/platform/embedder/embedder_render_target_impeller.h b/shell/platform/embedder/embedder_render_target_impeller.h new file mode 100644 index 0000000000000..2425402008f8a --- /dev/null +++ b/shell/platform/embedder/embedder_render_target_impeller.h @@ -0,0 +1,44 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_IMPELLER_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_IMPELLER_H_ + +#include "flutter/shell/platform/embedder/embedder_render_target.h" + +namespace flutter { + +class EmbedderRenderTargetImpeller final : public EmbedderRenderTarget { + public: + EmbedderRenderTargetImpeller( + FlutterBackingStore backing_store, + std::shared_ptr aiks_context, + std::unique_ptr impeller_target, + fml::closure on_release); + + // |EmbedderRenderTarget| + ~EmbedderRenderTargetImpeller() override; + + // |EmbedderRenderTarget| + sk_sp GetSkiaSurface() const override; + + // |EmbedderRenderTarget| + impeller::RenderTarget* GetImpellerRenderTarget() const override; + + // |EmbedderRenderTarget| + std::shared_ptr GetAiksContext() const override; + + // |EmbedderRenderTarget| + SkISize GetRenderTargetSize() const override; + + private: + std::shared_ptr aiks_context_; + std::unique_ptr impeller_target_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderRenderTargetImpeller); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_IMPELLER_H_ diff --git a/shell/platform/embedder/embedder_render_target_skia.cc b/shell/platform/embedder/embedder_render_target_skia.cc new file mode 100644 index 0000000000000..e8d60ca60890f --- /dev/null +++ b/shell/platform/embedder/embedder_render_target_skia.cc @@ -0,0 +1,40 @@ +// 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 "flutter/shell/platform/embedder/embedder_render_target_skia.h" + +#include "flutter/fml/logging.h" + +namespace flutter { + +EmbedderRenderTargetSkia::EmbedderRenderTargetSkia( + FlutterBackingStore backing_store, + sk_sp render_surface, + fml::closure on_release) + : EmbedderRenderTarget(backing_store, std::move(on_release)), + render_surface_(std::move(render_surface)) { + FML_DCHECK(render_surface_); +} + +EmbedderRenderTargetSkia::~EmbedderRenderTargetSkia() = default; + +sk_sp EmbedderRenderTargetSkia::GetSkiaSurface() const { + return render_surface_; +} + +impeller::RenderTarget* EmbedderRenderTargetSkia::GetImpellerRenderTarget() + const { + return nullptr; +} + +std::shared_ptr +EmbedderRenderTargetSkia::GetAiksContext() const { + return nullptr; +} + +SkISize EmbedderRenderTargetSkia::GetRenderTargetSize() const { + return SkISize::Make(render_surface_->width(), render_surface_->height()); +} + +} // namespace flutter diff --git a/shell/platform/embedder/embedder_render_target_skia.h b/shell/platform/embedder/embedder_render_target_skia.h new file mode 100644 index 0000000000000..2ccacfee33a2e --- /dev/null +++ b/shell/platform/embedder/embedder_render_target_skia.h @@ -0,0 +1,41 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_SKIA_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_SKIA_H_ + +#include "flutter/shell/platform/embedder/embedder_render_target.h" + +namespace flutter { + +class EmbedderRenderTargetSkia final : public EmbedderRenderTarget { + public: + EmbedderRenderTargetSkia(FlutterBackingStore backing_store, + sk_sp render_surface, + fml::closure on_release); + + // |EmbedderRenderTarget| + ~EmbedderRenderTargetSkia() override; + + // |EmbedderRenderTarget| + sk_sp GetSkiaSurface() const override; + + // |EmbedderRenderTarget| + impeller::RenderTarget* GetImpellerRenderTarget() const override; + + // |EmbedderRenderTarget| + std::shared_ptr GetAiksContext() const override; + + // |EmbedderRenderTarget| + SkISize GetRenderTargetSize() const override; + + private: + sk_sp render_surface_; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderRenderTargetSkia); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_SKIA_H_ diff --git a/shell/platform/embedder/embedder_surface.cc b/shell/platform/embedder/embedder_surface.cc index dbe619b8e0fa7..029833f7434ba 100644 --- a/shell/platform/embedder/embedder_surface.cc +++ b/shell/platform/embedder/embedder_surface.cc @@ -10,4 +10,13 @@ EmbedderSurface::EmbedderSurface() = default; EmbedderSurface::~EmbedderSurface() = default; +std::shared_ptr EmbedderSurface::CreateImpellerContext() + const { + return nullptr; +} + +sk_sp EmbedderSurface::CreateResourceContext() const { + return nullptr; +} + } // namespace flutter diff --git a/shell/platform/embedder/embedder_surface.h b/shell/platform/embedder/embedder_surface.h index ed8dbff74b8d0..32873f1a944a5 100644 --- a/shell/platform/embedder/embedder_surface.h +++ b/shell/platform/embedder/embedder_surface.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_H_ #define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_H_ +#include #include "flutter/flow/embedded_views.h" #include "flutter/flow/surface.h" #include "flutter/fml/macros.h" @@ -21,7 +22,9 @@ class EmbedderSurface { virtual std::unique_ptr CreateGPUSurface() = 0; - virtual sk_sp CreateResourceContext() const = 0; + virtual std::shared_ptr CreateImpellerContext() const; + + virtual sk_sp CreateResourceContext() const; private: FML_DISALLOW_COPY_AND_ASSIGN(EmbedderSurface); diff --git a/shell/platform/embedder/embedder_surface_metal_impeller.h b/shell/platform/embedder/embedder_surface_metal_impeller.h new file mode 100644 index 0000000000000..4fb2b990029c6 --- /dev/null +++ b/shell/platform/embedder/embedder_surface_metal_impeller.h @@ -0,0 +1,70 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_METAL_IMPELLER_H_ +#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_METAL_IMPELLER_H_ + +#include +#include "flutter/fml/macros.h" +#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" +#include "flutter/shell/gpu/gpu_surface_metal_skia.h" +#include "flutter/shell/platform/embedder/embedder_external_view_embedder.h" +#include "flutter/shell/platform/embedder/embedder_surface.h" +#include "fml/concurrent_message_loop.h" + +namespace impeller { +class Context; +} + +namespace flutter { + +class EmbedderSurfaceMetalImpeller final : public EmbedderSurface, + public GPUSurfaceMetalDelegate { + public: + struct MetalDispatchTable { + std::function present; // required + std::function + get_texture; // required + }; + + EmbedderSurfaceMetalImpeller( + GPUMTLDeviceHandle device, + GPUMTLCommandQueueHandle command_queue, + MetalDispatchTable dispatch_table, + std::shared_ptr external_view_embedder); + + ~EmbedderSurfaceMetalImpeller() override; + + private: + bool valid_ = false; + MetalDispatchTable metal_dispatch_table_; + std::shared_ptr external_view_embedder_; + std::shared_ptr context_; + std::shared_ptr concurrent_loop_; + + // |EmbedderSurface| + bool IsValid() const override; + + // |EmbedderSurface| + std::unique_ptr CreateGPUSurface() override; + + // |GPUSurfaceMetalDelegate| + GPUCAMetalLayerHandle GetCAMetalLayer( + const SkISize& frame_size) const override; + + // |GPUSurfaceMetalDelegate| + bool PresentDrawable(GrMTLHandle drawable) const override; + + // |GPUSurfaceMetalDelegate| + GPUMTLTextureInfo GetMTLTexture(const SkISize& frame_size) const override; + + // |GPUSurfaceMetalDelegate| + bool PresentTexture(GPUMTLTextureInfo texture) const override; + + FML_DISALLOW_COPY_AND_ASSIGN(EmbedderSurfaceMetalImpeller); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_METAL_IMPELLER_H_ diff --git a/shell/platform/embedder/embedder_surface_metal_impeller.mm b/shell/platform/embedder/embedder_surface_metal_impeller.mm new file mode 100644 index 0000000000000..c7984f4f386ef --- /dev/null +++ b/shell/platform/embedder/embedder_surface_metal_impeller.mm @@ -0,0 +1,97 @@ +// 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 +#include + +#include "flutter/shell/platform/embedder/embedder_surface_metal_impeller.h" + +#include "flutter/fml/logging.h" +#include "flutter/fml/synchronization/sync_switch.h" +#include "flutter/shell/gpu/gpu_surface_metal_delegate.h" +#include "flutter/shell/gpu/gpu_surface_metal_impeller.h" +#import "flutter/shell/platform/darwin/graphics/FlutterDarwinContextMetalImpeller.h" +#include "impeller/entity/mtl/entity_shaders.h" +#include "impeller/entity/mtl/framebuffer_blend_shaders.h" +#include "impeller/entity/mtl/modern_shaders.h" +#include "impeller/renderer/backend/metal/context_mtl.h" +#include "impeller/scene/shaders/mtl/scene_shaders.h" + +FLUTTER_ASSERT_NOT_ARC + +namespace flutter { + +EmbedderSurfaceMetalImpeller::EmbedderSurfaceMetalImpeller( + GPUMTLDeviceHandle device, + GPUMTLCommandQueueHandle command_queue, + MetalDispatchTable metal_dispatch_table, + std::shared_ptr external_view_embedder) + : GPUSurfaceMetalDelegate(MTLRenderTargetType::kMTLTexture), + metal_dispatch_table_(std::move(metal_dispatch_table)), + external_view_embedder_(std::move(external_view_embedder)), + concurrent_loop_(fml::ConcurrentMessageLoop::Create()) { + std::vector> shader_mappings = { + std::make_shared(impeller_entity_shaders_data, + impeller_entity_shaders_length), + std::make_shared(impeller_scene_shaders_data, + impeller_scene_shaders_length), + std::make_shared(impeller_modern_shaders_data, + impeller_modern_shaders_length), + std::make_shared(impeller_framebuffer_blend_shaders_data, + impeller_framebuffer_blend_shaders_length), + }; + context_ = impeller::ContextMTL::Create( + (id)device, // device + (id)command_queue, // command_queue + shader_mappings, // shader_libraries_data + concurrent_loop_->GetTaskRunner(), // worker_task_runner + std::make_shared(false), // is_gpu_disabled_sync_switch + "Impeller Library" // library_label + ); + + valid_ = !!context_; +} + +EmbedderSurfaceMetalImpeller::~EmbedderSurfaceMetalImpeller() = default; + +bool EmbedderSurfaceMetalImpeller::IsValid() const { + return valid_; +} + +std::unique_ptr EmbedderSurfaceMetalImpeller::CreateGPUSurface() + IMPELLER_CA_METAL_LAYER_AVAILABLE { + if (!IsValid()) { + return nullptr; + } + + const bool render_to_surface = !external_view_embedder_; + auto surface = std::make_unique(this, context_, render_to_surface); + + if (!surface->IsValid()) { + return nullptr; + } + + return surface; +} + +GPUCAMetalLayerHandle EmbedderSurfaceMetalImpeller::GetCAMetalLayer( + const SkISize& frame_info) const { + FML_CHECK(false) << "Only rendering to MTLTexture is supported."; + return nullptr; +} + +bool EmbedderSurfaceMetalImpeller::PresentDrawable(GrMTLHandle drawable) const { + FML_CHECK(false) << "Only rendering to MTLTexture is supported."; + return false; +} + +GPUMTLTextureInfo EmbedderSurfaceMetalImpeller::GetMTLTexture(const SkISize& frame_info) const { + return metal_dispatch_table_.get_texture(frame_info); +} + +bool EmbedderSurfaceMetalImpeller::PresentTexture(GPUMTLTextureInfo texture) const { + return metal_dispatch_table_.present(texture); +} + +} // namespace flutter diff --git a/shell/platform/embedder/platform_view_embedder.cc b/shell/platform/embedder/platform_view_embedder.cc index 1cedc22810a50..ccbe0fc01a524 100644 --- a/shell/platform/embedder/platform_view_embedder.cc +++ b/shell/platform/embedder/platform_view_embedder.cc @@ -86,7 +86,7 @@ PlatformViewEmbedder::PlatformViewEmbedder( PlatformViewEmbedder::PlatformViewEmbedder( PlatformView::Delegate& delegate, const flutter::TaskRunners& task_runners, - std::unique_ptr embedder_surface, + std::unique_ptr embedder_surface, PlatformDispatchTable platform_dispatch_table, std::shared_ptr external_view_embedder) : PlatformView(delegate, task_runners), @@ -157,6 +157,11 @@ PlatformViewEmbedder::CreateExternalViewEmbedder() { return external_view_embedder_; } +std::shared_ptr PlatformViewEmbedder::GetImpellerContext() + const { + return embedder_surface_->CreateImpellerContext(); +} + // |PlatformView| sk_sp PlatformViewEmbedder::CreateResourceContext() const { if (embedder_surface_ == nullptr) { diff --git a/shell/platform/embedder/platform_view_embedder.h b/shell/platform/embedder/platform_view_embedder.h index 20f4dc139875b..87378b5074672 100644 --- a/shell/platform/embedder/platform_view_embedder.h +++ b/shell/platform/embedder/platform_view_embedder.h @@ -76,7 +76,7 @@ class PlatformViewEmbedder final : public PlatformView { PlatformViewEmbedder( PlatformView::Delegate& delegate, const flutter::TaskRunners& task_runners, - std::unique_ptr embedder_surface, + std::unique_ptr embedder_surface, PlatformDispatchTable platform_dispatch_table, std::shared_ptr external_view_embedder); #endif @@ -118,6 +118,9 @@ class PlatformViewEmbedder final : public PlatformView { // |PlatformView| std::shared_ptr CreateExternalViewEmbedder() override; + // |PlatformView| + std::shared_ptr GetImpellerContext() const override; + // |PlatformView| sk_sp CreateResourceContext() const override; diff --git a/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc b/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc index 901bd8c078e97..366b72bc0b429 100644 --- a/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc +++ b/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc @@ -132,6 +132,7 @@ void FlatlandExternalViewEmbedder::EndFrame( void FlatlandExternalViewEmbedder::SubmitFrame( GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) { TRACE_EVENT0("flutter", "FlatlandExternalViewEmbedder::SubmitFrame"); std::vector> frame_surfaces; diff --git a/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h b/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h index 00a845cde2e85..5a3142eb5d2f6 100644 --- a/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h +++ b/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h @@ -87,6 +87,7 @@ class FlatlandExternalViewEmbedder final // |ExternalViewEmbedder| void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override; // |ExternalViewEmbedder| diff --git a/shell/platform/fuchsia/flutter/gfx_external_view_embedder.cc b/shell/platform/fuchsia/flutter/gfx_external_view_embedder.cc index 21c6810c4e11b..37e8d6a474431 100644 --- a/shell/platform/fuchsia/flutter/gfx_external_view_embedder.cc +++ b/shell/platform/fuchsia/flutter/gfx_external_view_embedder.cc @@ -231,6 +231,7 @@ void GfxExternalViewEmbedder::EndFrame( void GfxExternalViewEmbedder::SubmitFrame( GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) { TRACE_EVENT0("flutter", "GfxExternalViewEmbedder::SubmitFrame"); std::vector> frame_surfaces; diff --git a/shell/platform/fuchsia/flutter/gfx_external_view_embedder.h b/shell/platform/fuchsia/flutter/gfx_external_view_embedder.h index eb37d2e7e2d1f..6d0bc30061047 100644 --- a/shell/platform/fuchsia/flutter/gfx_external_view_embedder.h +++ b/shell/platform/fuchsia/flutter/gfx_external_view_embedder.h @@ -110,6 +110,7 @@ class GfxExternalViewEmbedder final : public flutter::ExternalViewEmbedder { // |ExternalViewEmbedder| void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override; // |ExternalViewEmbedder| diff --git a/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/shell/platform/fuchsia/flutter/platform_view_unittest.cc index 4959461c8a115..c0aa42e0a5dbf 100644 --- a/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -54,6 +54,7 @@ class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder { fml::RefPtr raster_thread_merger) override {} void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override {} void PrerollCompositeEmbeddedView( diff --git a/shell/platform/fuchsia/flutter/tests/flatland_external_view_embedder_unittests.cc b/shell/platform/fuchsia/flutter/tests/flatland_external_view_embedder_unittests.cc index 35f734d2044ac..58af0ccb88526 100644 --- a/shell/platform/fuchsia/flutter/tests/flatland_external_view_embedder_unittests.cc +++ b/shell/platform/fuchsia/flutter/tests/flatland_external_view_embedder_unittests.cc @@ -335,11 +335,12 @@ void DrawSimpleFrame(FlatlandExternalViewEmbedder& external_view_embedder, flutter::SurfaceFrame::FramebufferInfo framebuffer_info; framebuffer_info.supports_readback = true; external_view_embedder.SubmitFrame( - nullptr, std::make_unique( - nullptr, std::move(framebuffer_info), - [](const flutter::SurfaceFrame& surface_frame, - flutter::DlCanvas* canvas) { return true; }, - frame_size)); + nullptr, nullptr, + std::make_unique( + nullptr, std::move(framebuffer_info), + [](const flutter::SurfaceFrame& surface_frame, + flutter::DlCanvas* canvas) { return true; }, + frame_size)); } void DrawFrameWithView( @@ -365,11 +366,12 @@ void DrawFrameWithView( flutter::SurfaceFrame::FramebufferInfo framebuffer_info; framebuffer_info.supports_readback = true; external_view_embedder.SubmitFrame( - nullptr, std::make_unique( - nullptr, std::move(framebuffer_info), - [](const flutter::SurfaceFrame& surface_frame, - flutter::DlCanvas* canvas) { return true; }, - frame_size)); + nullptr, nullptr, + std::make_unique( + nullptr, std::move(framebuffer_info), + [](const flutter::SurfaceFrame& surface_frame, + flutter::DlCanvas* canvas) { return true; }, + frame_size)); } }; // namespace diff --git a/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc b/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc index ce1d55fdc1c91..78f6f9588958a 100644 --- a/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc +++ b/shell/platform/fuchsia/flutter/tests/flatland_platform_view_unittest.cc @@ -53,6 +53,7 @@ class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder { fml::RefPtr raster_thread_merger) override {} void SubmitFrame(GrDirectContext* context, + const std::shared_ptr& aiks_context, std::unique_ptr frame) override {} void PrerollCompositeEmbeddedView( diff --git a/shell/platform/fuchsia/flutter/tests/gfx_external_view_embedder_unittests.cc b/shell/platform/fuchsia/flutter/tests/gfx_external_view_embedder_unittests.cc index 77c04bb6ab7ed..eba9a2dc0ad5c 100644 --- a/shell/platform/fuchsia/flutter/tests/gfx_external_view_embedder_unittests.cc +++ b/shell/platform/fuchsia/flutter/tests/gfx_external_view_embedder_unittests.cc @@ -458,11 +458,12 @@ void DrawSimpleFrame(GfxExternalViewEmbedder& external_view_embedder, external_view_embedder.EndFrame(false, nullptr); flutter::SurfaceFrame::FramebufferInfo framebuffer_info; external_view_embedder.SubmitFrame( - nullptr, std::make_unique( - nullptr, framebuffer_info, - [](const flutter::SurfaceFrame& surface_frame, - flutter::DlCanvas* canvas) { return true; }, - frame_size)); + nullptr, nullptr, + std::make_unique( + nullptr, framebuffer_info, + [](const flutter::SurfaceFrame& surface_frame, + flutter::DlCanvas* canvas) { return true; }, + frame_size)); } void DrawFrameWithView( @@ -487,11 +488,12 @@ void DrawFrameWithView( external_view_embedder.EndFrame(false, nullptr); flutter::SurfaceFrame::FramebufferInfo framebuffer_info; external_view_embedder.SubmitFrame( - nullptr, std::make_unique( - nullptr, framebuffer_info, - [](const flutter::SurfaceFrame& surface_frame, - flutter::DlCanvas* canvas) { return true; }, - frame_size)); + nullptr, nullptr, + std::make_unique( + nullptr, framebuffer_info, + [](const flutter::SurfaceFrame& surface_frame, + flutter::DlCanvas* canvas) { return true; }, + frame_size)); } FramePresentedInfo MakeFramePresentedInfoForOnePresent( From 3aebe098249540ece2dc57bb54fd79c4cff4c8ff Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 3 Jun 2023 21:39:44 -0700 Subject: [PATCH 2/2] Always set the wrapped texture descriptor to the correct size --- .../renderer/backend/metal/surface_mtl.mm | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index 7ff1810d1751f..f3b3de4a419cb 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -45,24 +45,10 @@ id texture, bool requires_blit, std::optional clip_rect) { - // compositor_context.cc will offset the rendering by the clip origin. Here we - // shrink to the size of the clip. This has the same effect as clipping the - // rendering but also creates smaller intermediate passes. - ISize root_size; - if (requires_blit) { - if (!clip_rect.has_value()) { - VALIDATION_LOG << "Missing clip rectangle."; - return std::nullopt; - } - root_size = ISize(clip_rect->size.width, clip_rect->size.height); - } else { - root_size = {static_cast(texture.width), - static_cast(texture.height)}; - } - TextureDescriptor resolve_tex_desc; resolve_tex_desc.format = FromMTLPixelFormat(texture.pixelFormat); - resolve_tex_desc.size = root_size; + resolve_tex_desc.size = {static_cast(texture.width), + static_cast(texture.height)}; resolve_tex_desc.usage = static_cast(TextureUsage::kRenderTarget) | static_cast(TextureUsage::kShaderRead); resolve_tex_desc.sample_count = SampleCount::kCount1; @@ -110,8 +96,8 @@ color0.store_action = StoreAction::kMultisampleResolve; color0.resolve_texture = std::move(resolve_tex); - RenderTarget render_target_desc; - render_target_desc.SetColorAttachment(color0, 0u); + auto render_target_desc = std::make_optional(); + render_target_desc->SetColorAttachment(color0, 0u); return render_target_desc; }