mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Reland: Add Impeller Metal support in the embedder API (#42411) (flutter/engine#42545)
This reverts commit
45dd178414.
Original PR: https://github.com/flutter/engine/pull/42411
Part of https://github.com/flutter/flutter/issues/112230.
This commit is contained in:
parent
cd6f44c544
commit
fba5e2b514
@ -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
|
||||
|
||||
@ -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" ]
|
||||
}
|
||||
|
||||
|
||||
@ -42,8 +42,10 @@ bool DisplayListEmbedderViewSlice::recording_ended() {
|
||||
return builder_ == nullptr;
|
||||
}
|
||||
|
||||
void ExternalViewEmbedder::SubmitFrame(GrDirectContext* context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
void ExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
frame->Submit();
|
||||
};
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#ifndef FLUTTER_FLOW_EMBEDDED_VIEWS_H_
|
||||
#define FLUTTER_FLOW_EMBEDDED_VIEWS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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<SurfaceFrame> frame);
|
||||
virtual void SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame);
|
||||
|
||||
// This method provides the embedder a way to do additional tasks after
|
||||
// |SubmitFrame|. For example, merge task runners if `should_resubmit_frame`
|
||||
|
||||
@ -121,7 +121,7 @@ std::unique_ptr<Surface> PlaygroundImplMTL::AcquireSurfaceFrame(
|
||||
|
||||
auto drawable =
|
||||
SurfaceMTL::GetMetalDrawableAndValidate(context, data_->metal_layer);
|
||||
return SurfaceMTL::WrapCurrentMetalLayerDrawable(context, drawable);
|
||||
return SurfaceMTL::MakeFromMetalLayerDrawable(context, drawable);
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -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",
|
||||
]
|
||||
|
||||
@ -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<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
|
||||
const std::string& label);
|
||||
|
||||
static std::shared_ptr<ContextMTL> Create(
|
||||
id<MTLDevice> device,
|
||||
id<MTLCommandQueue> command_queue,
|
||||
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner,
|
||||
std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
|
||||
const std::string& label);
|
||||
|
||||
// |Context|
|
||||
~ContextMTL() override;
|
||||
|
||||
@ -90,6 +104,7 @@ class ContextMTL final : public Context,
|
||||
|
||||
ContextMTL(
|
||||
id<MTLDevice> device,
|
||||
id<MTLCommandQueue> command_queue,
|
||||
NSArray<id<MTLLibrary>>* shader_libraries,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner,
|
||||
std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch);
|
||||
|
||||
@ -6,9 +6,11 @@
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#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 std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||
|
||||
ContextMTL::ContextMTL(
|
||||
id<MTLDevice> device,
|
||||
id<MTLCommandQueue> command_queue,
|
||||
NSArray<id<MTLLibrary>>* shader_libraries,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner,
|
||||
std::shared_ptr<const fml::SyncSwitch> 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 @@ ContextMTL::ContextMTL(
|
||||
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 id<MTLDevice> CreateMetalDevice() {
|
||||
return ::MTLCreateSystemDefaultDevice();
|
||||
}
|
||||
|
||||
static id<MTLCommandQueue> CreateMetalCommandQueue(id<MTLDevice> 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> ContextMTL::Create(
|
||||
const std::vector<std::string>& shader_library_paths,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner,
|
||||
std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch) {
|
||||
auto device = CreateMetalDevice();
|
||||
auto command_queue = CreateMetalCommandQueue(device);
|
||||
if (!command_queue) {
|
||||
return nullptr;
|
||||
}
|
||||
auto context = std::shared_ptr<ContextMTL>(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 @@ std::shared_ptr<ContextMTL> ContextMTL::Create(
|
||||
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner,
|
||||
std::shared_ptr<const fml::SyncSwitch> 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<ContextMTL>(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.";
|
||||
return nullptr;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
std::shared_ptr<ContextMTL> ContextMTL::Create(
|
||||
id<MTLDevice> device,
|
||||
id<MTLCommandQueue> command_queue,
|
||||
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
|
||||
std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner,
|
||||
std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
|
||||
const std::string& library_label) {
|
||||
auto context = std::shared_ptr<ContextMTL>(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.";
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QuartzCore/CAMetalLayer.h>
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/geometry/rect.h"
|
||||
@ -37,10 +38,15 @@ class SurfaceMTL final : public Surface {
|
||||
const std::shared_ptr<Context>& context,
|
||||
CAMetalLayer* layer);
|
||||
|
||||
static std::unique_ptr<SurfaceMTL> WrapCurrentMetalLayerDrawable(
|
||||
static std::unique_ptr<SurfaceMTL> MakeFromMetalLayerDrawable(
|
||||
const std::shared_ptr<Context>& context,
|
||||
id<CAMetalDrawable> drawable,
|
||||
std::optional<IRect> clip_rect = std::nullopt);
|
||||
|
||||
static std::unique_ptr<SurfaceMTL> MakeFromTexture(
|
||||
const std::shared_ptr<Context>& context,
|
||||
id<MTLTexture> texture,
|
||||
std::optional<IRect> clip_rect);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// |Surface|
|
||||
@ -58,6 +64,8 @@ class SurfaceMTL final : public Surface {
|
||||
std::weak_ptr<Context> context_;
|
||||
std::shared_ptr<Texture> resolve_texture_;
|
||||
id<CAMetalDrawable> drawable_ = nil;
|
||||
std::shared_ptr<Texture> source_texture_;
|
||||
std::shared_ptr<Texture> destination_texture_;
|
||||
bool requires_blit_ = false;
|
||||
std::optional<IRect> clip_rect_;
|
||||
|
||||
@ -67,6 +75,8 @@ class SurfaceMTL final : public Surface {
|
||||
const RenderTarget& target,
|
||||
std::shared_ptr<Texture> resolve_texture,
|
||||
id<CAMetalDrawable> drawable,
|
||||
std::shared_ptr<Texture> source_texture,
|
||||
std::shared_ptr<Texture> destination_texture,
|
||||
bool requires_blit,
|
||||
std::optional<IRect> clip_rect);
|
||||
|
||||
|
||||
@ -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,98 +40,142 @@ id<CAMetalDrawable> SurfaceMTL::GetMetalDrawableAndValidate(
|
||||
return current_drawable;
|
||||
}
|
||||
|
||||
std::unique_ptr<SurfaceMTL> SurfaceMTL::WrapCurrentMetalLayerDrawable(
|
||||
const std::shared_ptr<Context>& context,
|
||||
id<CAMetalDrawable> drawable,
|
||||
static std::optional<RenderTarget> WrapTextureWithRenderTarget(
|
||||
Allocator& allocator,
|
||||
id<MTLTexture> texture,
|
||||
bool requires_blit,
|
||||
std::optional<IRect> 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.
|
||||
ISize root_size;
|
||||
if (requires_blit) {
|
||||
if (!clip_rect.has_value()) {
|
||||
VALIDATION_LOG << "Missing clip rectangle.";
|
||||
return nullptr;
|
||||
}
|
||||
root_size = ISize(clip_rect->size.width, clip_rect->size.height);
|
||||
} else {
|
||||
root_size = {static_cast<ISize::Type>(drawable.texture.width),
|
||||
static_cast<ISize::Type>(drawable.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<uint64_t>(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 = {static_cast<ISize::Type>(texture.width),
|
||||
static_cast<ISize::Type>(texture.height)};
|
||||
resolve_tex_desc.usage = static_cast<uint64_t>(TextureUsage::kRenderTarget) |
|
||||
static_cast<uint64_t>(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<Texture> 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<TextureMTL>(resolve_tex_desc, drawable.texture);
|
||||
resolve_tex = std::make_shared<TextureMTL>(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<uint64_t>(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);
|
||||
auto render_target_desc = std::make_optional<RenderTarget>();
|
||||
render_target_desc->SetColorAttachment(color0, 0u);
|
||||
|
||||
// The constructor is private. So make_unique may not be used.
|
||||
return std::unique_ptr<SurfaceMTL>(new SurfaceMTL(context, render_target_desc,
|
||||
resolve_tex, drawable,
|
||||
requires_blit, clip_rect));
|
||||
return render_target_desc;
|
||||
}
|
||||
|
||||
std::unique_ptr<SurfaceMTL> SurfaceMTL::MakeFromMetalLayerDrawable(
|
||||
const std::shared_ptr<Context>& context,
|
||||
id<CAMetalDrawable> drawable,
|
||||
std::optional<IRect> 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<SurfaceMTL>(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> SurfaceMTL::MakeFromTexture(
|
||||
const std::shared_ptr<Context>& context,
|
||||
id<MTLTexture> texture,
|
||||
std::optional<IRect> 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<SurfaceMTL>(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>& context,
|
||||
const RenderTarget& target,
|
||||
std::shared_ptr<Texture> resolve_texture,
|
||||
id<CAMetalDrawable> drawable,
|
||||
std::shared_ptr<Texture> source_texture,
|
||||
std::shared_ptr<Texture> destination_texture,
|
||||
bool requires_blit,
|
||||
std::optional<IRect> 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 +218,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 +237,7 @@ bool SurfaceMTL::Present() const {
|
||||
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 +245,15 @@ bool SurfaceMTL::Present() const {
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldWaitForCommandBuffer()) {
|
||||
id<MTLCommandBuffer> command_buffer =
|
||||
ContextMTL::Cast(context.get())->CreateMTLCommandBuffer();
|
||||
[command_buffer commit];
|
||||
[command_buffer waitUntilScheduled];
|
||||
if (drawable_) {
|
||||
if (ShouldWaitForCommandBuffer()) {
|
||||
id<MTLCommandBuffer> command_buffer =
|
||||
ContextMTL::Cast(context.get())->CreateMTLCommandBuffer();
|
||||
[command_buffer commit];
|
||||
[command_buffer waitUntilScheduled];
|
||||
}
|
||||
[drawable_ present];
|
||||
}
|
||||
[drawable_ present];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -19,8 +19,10 @@ class TextureMTL final : public Texture,
|
||||
id<MTLTexture> texture,
|
||||
bool wrapped = false);
|
||||
|
||||
static std::shared_ptr<TextureMTL> Wrapper(TextureDescriptor desc,
|
||||
id<MTLTexture> texture);
|
||||
static std::shared_ptr<TextureMTL> Wrapper(
|
||||
TextureDescriptor desc,
|
||||
id<MTLTexture> texture,
|
||||
std::function<void()> deletion_proc = nullptr);
|
||||
|
||||
// |Texture|
|
||||
~TextureMTL() override;
|
||||
|
||||
@ -9,6 +9,13 @@
|
||||
|
||||
namespace impeller {
|
||||
|
||||
std::shared_ptr<Texture> WrapperMTL(TextureDescriptor desc,
|
||||
const void* mtl_texture,
|
||||
std::function<void()> deletion_proc) {
|
||||
return TextureMTL::Wrapper(desc, (__bridge id<MTLTexture>)mtl_texture,
|
||||
std::move(deletion_proc));
|
||||
}
|
||||
|
||||
TextureMTL::TextureMTL(TextureDescriptor p_desc,
|
||||
id<MTLTexture> texture,
|
||||
bool wrapped)
|
||||
@ -28,9 +35,18 @@ TextureMTL::TextureMTL(TextureDescriptor p_desc,
|
||||
is_valid_ = true;
|
||||
}
|
||||
|
||||
std::shared_ptr<TextureMTL> TextureMTL::Wrapper(TextureDescriptor desc,
|
||||
id<MTLTexture> texture) {
|
||||
return std::make_shared<TextureMTL>(desc, texture, true);
|
||||
std::shared_ptr<TextureMTL> TextureMTL::Wrapper(
|
||||
TextureDescriptor desc,
|
||||
id<MTLTexture> texture,
|
||||
std::function<void()> deletion_proc) {
|
||||
if (deletion_proc) {
|
||||
return std::shared_ptr<TextureMTL>(
|
||||
new TextureMTL(desc, texture, true),
|
||||
[deletion_proc = std::move(deletion_proc)](TextureMTL* t) {
|
||||
deletion_proc();
|
||||
});
|
||||
}
|
||||
return std::shared_ptr<TextureMTL>(new TextureMTL(desc, texture, true));
|
||||
}
|
||||
|
||||
TextureMTL::~TextureMTL() = default;
|
||||
|
||||
@ -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<Texture> WrapTextureMTL(
|
||||
TextureDescriptor desc,
|
||||
const void* mtl_texture,
|
||||
std::function<void()> deletion_proc = nullptr);
|
||||
|
||||
} // namespace impeller
|
||||
@ -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 <Metal/Metal.h>
|
||||
|
||||
#include "impeller/renderer/backend/metal/formats_mtl.h"
|
||||
#include "impeller/renderer/backend/metal/texture_mtl.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
std::shared_ptr<Texture> WrapTextureMTL(TextureDescriptor desc,
|
||||
const void* mtl_texture,
|
||||
std::function<void()> deletion_proc) {
|
||||
auto texture = (__bridge id<MTLTexture>)mtl_texture;
|
||||
desc.format = FromMTLPixelFormat(texture.pixelFormat);
|
||||
return TextureMTL::Wrapper(desc, texture, std::move(deletion_proc));
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -74,8 +74,9 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
PostPrerollResult(
|
||||
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger));
|
||||
MOCK_METHOD1(CompositeEmbeddedView, DlCanvas*(int64_t view_id));
|
||||
MOCK_METHOD2(SubmitFrame,
|
||||
MOCK_METHOD3(SubmitFrame,
|
||||
void(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame));
|
||||
MOCK_METHOD2(EndFrame,
|
||||
void(bool should_resubmit_frame,
|
||||
|
||||
@ -91,6 +91,7 @@ DlCanvas* ShellTestExternalViewEmbedder::CompositeEmbeddedView(
|
||||
// |ExternalViewEmbedder|
|
||||
void ShellTestExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
if (!frame) {
|
||||
return;
|
||||
|
||||
@ -75,6 +75,7 @@ class ShellTestExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
|
||||
@ -5,22 +5,25 @@
|
||||
#ifndef FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_IMPELLER_H_
|
||||
#define FLUTTER_SHELL_GPU_GPU_SURFACE_METAL_IMPELLER_H_
|
||||
|
||||
#include <QuartzCore/CAMetalLayer.h>
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
#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<impeller::Context>& context);
|
||||
const std::shared_ptr<impeller::Context>& 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> impeller_renderer_;
|
||||
std::shared_ptr<impeller::AiksContext> aiks_context_;
|
||||
fml::scoped_nsprotocol<id<MTLDrawable>> last_drawable_;
|
||||
fml::scoped_nsprotocol<id<MTLTexture>> 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<uintptr_t, SkIRect> damage_;
|
||||
|
||||
// |Surface|
|
||||
std::unique_ptr<SurfaceFrame> AcquireFrame(const SkISize& size) override;
|
||||
std::unique_ptr<SurfaceFrame> AcquireFrame(
|
||||
const SkISize& frame_size) override;
|
||||
|
||||
std::unique_ptr<SurfaceFrame> AcquireFrameFromCAMetalLayer(
|
||||
const SkISize& frame_size);
|
||||
|
||||
std::unique_ptr<SurfaceFrame> AcquireFrameFromMTLTexture(
|
||||
const SkISize& frame_size);
|
||||
|
||||
// |Surface|
|
||||
SkMatrix GetRootTransformation() const override;
|
||||
|
||||
@ -29,11 +29,14 @@ static std::shared_ptr<impeller::Renderer> CreateImpellerRenderer(
|
||||
}
|
||||
|
||||
GPUSurfaceMetalImpeller::GPUSurfaceMetalImpeller(GPUSurfaceMetalDelegate* delegate,
|
||||
const std::shared_ptr<impeller::Context>& context)
|
||||
const std::shared_ptr<impeller::Context>& context,
|
||||
bool render_to_surface)
|
||||
: delegate_(delegate),
|
||||
render_target_type_(delegate->GetRenderTargetType()),
|
||||
impeller_renderer_(CreateImpellerRenderer(context)),
|
||||
aiks_context_(
|
||||
std::make_shared<impeller::AiksContext>(impeller_renderer_ ? context : nullptr)) {
|
||||
std::make_shared<impeller::AiksContext>(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 @@ bool GPUSurfaceMetalImpeller::IsValid() {
|
||||
}
|
||||
|
||||
// |Surface|
|
||||
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISize& frame_info) {
|
||||
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISize& frame_size) {
|
||||
TRACE_EVENT0("impeller", "GPUSurfaceMetalImpeller::AcquireFrame");
|
||||
|
||||
if (!IsValid()) {
|
||||
@ -58,7 +61,33 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
|
||||
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<SurfaceFrame>(
|
||||
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<SurfaceFrame> 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 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
|
||||
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<CAMetalDrawable> metal_drawable = static_cast<id<CAMetalDrawable>>(last_drawable_);
|
||||
id<MTLTexture> last_texture = static_cast<id<MTLTexture>>(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 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
|
||||
}
|
||||
|
||||
if (!disable_partial_repaint_) {
|
||||
uintptr_t texture = reinterpret_cast<uintptr_t>(metal_drawable.texture);
|
||||
uintptr_t texture = reinterpret_cast<uintptr_t>(last_texture);
|
||||
|
||||
for (auto& entry : damage_) {
|
||||
if (entry.first != texture) {
|
||||
@ -111,8 +141,8 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
|
||||
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();
|
||||
@ -138,7 +168,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
|
||||
if (!disable_partial_repaint_) {
|
||||
// Provide accumulated damage to rasterizer (area in current framebuffer that lags behind
|
||||
// front buffer)
|
||||
uintptr_t texture = reinterpret_cast<uintptr_t>(metal_drawable.texture);
|
||||
uintptr_t texture = reinterpret_cast<uintptr_t>(drawable.texture);
|
||||
auto i = damage_.find(texture);
|
||||
if (i != damage_.end()) {
|
||||
framebuffer_info.existing_damage = i->second;
|
||||
@ -149,7 +179,107 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrame(const SkISiz
|
||||
return std::make_unique<SurfaceFrame>(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
|
||||
);
|
||||
}
|
||||
|
||||
std::unique_ptr<SurfaceFrame> GPUSurfaceMetalImpeller::AcquireFrameFromMTLTexture(
|
||||
const SkISize& frame_size) {
|
||||
GPUMTLTextureInfo texture_info = delegate_->GetMTLTexture(frame_size);
|
||||
id<MTLTexture> mtl_texture = (id<MTLTexture>)(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<uintptr_t>(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<impeller::IRect> 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();
|
||||
}
|
||||
|
||||
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);
|
||||
}));
|
||||
|
||||
delegate->PresentTexture(texture_info);
|
||||
});
|
||||
|
||||
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<uintptr_t>(mtl_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<SurfaceFrame>(nullptr, // surface
|
||||
framebuffer_info, // framebuffer info
|
||||
submit_callback, // submit callback
|
||||
frame_size, // frame size
|
||||
nullptr, // context result
|
||||
true // display list fallback
|
||||
);
|
||||
@ -188,11 +318,10 @@ std::shared_ptr<impeller::AiksContext> GPUSurfaceMetalImpeller::GetAiksContext()
|
||||
}
|
||||
|
||||
Surface::SurfaceData GPUSurfaceMetalImpeller::GetSurfaceData() const {
|
||||
if (!(last_drawable_ && [last_drawable_ conformsToProtocol:@protocol(CAMetalDrawable)])) {
|
||||
if (!(last_texture_ && [last_texture_ conformsToProtocol:@protocol(MTLTexture)])) {
|
||||
return {};
|
||||
}
|
||||
id<CAMetalDrawable> metal_drawable = static_cast<id<CAMetalDrawable>>(last_drawable_);
|
||||
id<MTLTexture> texture = metal_drawable.texture;
|
||||
id<MTLTexture> texture = last_texture_.get();
|
||||
int bytesPerPixel = 0;
|
||||
std::string pixel_format;
|
||||
switch (texture.pixelFormat) {
|
||||
|
||||
@ -64,6 +64,7 @@ SkRect AndroidExternalViewEmbedder::GetViewRect(int64_t view_id) const {
|
||||
// |ExternalViewEmbedder|
|
||||
void AndroidExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame");
|
||||
|
||||
|
||||
@ -46,6 +46,7 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ class IOSExternalViewEmbedder : public ExternalViewEmbedder {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
|
||||
@ -66,8 +66,10 @@ DlCanvas* IOSExternalViewEmbedder::CompositeEmbeddedView(int64_t view_id) {
|
||||
}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void IOSExternalViewEmbedder::SubmitFrame(GrDirectContext* context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
void IOSExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "IOSExternalViewEmbedder::SubmitFrame");
|
||||
FML_CHECK(platform_views_controller_);
|
||||
platform_views_controller_->SubmitFrame(context, ios_context_, std::move(frame));
|
||||
|
||||
@ -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",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<flutter::EmbedderExternalViewEmbedder>
|
||||
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<flutter::EmbedderExternalViewEmbedder> view_embedder =
|
||||
std::move(external_view_embedder);
|
||||
|
||||
std::unique_ptr<flutter::EmbedderSurfaceMetal> embedder_surface =
|
||||
std::make_unique<flutter::EmbedderSurfaceMetal>(
|
||||
const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
|
||||
const_cast<flutter::GPUMTLCommandQueueHandle>(
|
||||
config->metal.present_command_queue),
|
||||
metal_dispatch_table, view_embedder);
|
||||
std::unique_ptr<flutter::EmbedderSurface> embedder_surface;
|
||||
|
||||
if (enable_impeller) {
|
||||
flutter::EmbedderSurfaceMetalImpeller::MetalDispatchTable
|
||||
metal_dispatch_table = {
|
||||
.present = metal_present,
|
||||
.get_texture = metal_get_texture,
|
||||
};
|
||||
embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetalImpeller>(
|
||||
const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
|
||||
const_cast<flutter::GPUMTLCommandQueueHandle>(
|
||||
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<flutter::EmbedderSurfaceMetal>(
|
||||
const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
|
||||
const_cast<flutter::GPUMTLCommandQueueHandle>(
|
||||
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<flutter::EmbedderExternalViewEmbedder>
|
||||
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<SkSurface> MakeSkSurfaceFromBackingStore(
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<flutter::EmbedderRenderTarget>
|
||||
MakeRenderTargetFromBackingStoreImpeller(
|
||||
FlutterBackingStore backing_store,
|
||||
const fml::closure& on_release,
|
||||
const std::shared_ptr<impeller::AiksContext>& 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<uint64_t>(impeller::TextureUsage::kRenderTarget) |
|
||||
static_cast<uint64_t>(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<uint64_t>(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<flutter::EmbedderRenderTargetImpeller>(
|
||||
backing_store, aiks_context,
|
||||
std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
|
||||
on_release);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
|
||||
GrDirectContext* context,
|
||||
const FlutterBackingStoreConfig& config,
|
||||
@ -953,9 +1046,23 @@ static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
|
||||
}
|
||||
|
||||
static std::unique_ptr<flutter::EmbedderRenderTarget>
|
||||
CreateEmbedderRenderTarget(const FlutterCompositor* compositor,
|
||||
const FlutterBackingStoreConfig& config,
|
||||
GrDirectContext* context) {
|
||||
MakeRenderTargetFromSkSurface(FlutterBackingStore backing_store,
|
||||
sk_sp<SkSurface> skia_surface,
|
||||
fml::closure on_release) {
|
||||
if (!skia_surface) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<flutter::EmbedderRenderTargetSkia>(
|
||||
backing_store, std::move(skia_surface), std::move(on_release));
|
||||
}
|
||||
|
||||
static std::unique_ptr<flutter::EmbedderRenderTarget>
|
||||
CreateEmbedderRenderTarget(
|
||||
const FlutterCompositor* compositor,
|
||||
const FlutterBackingStoreConfig& config,
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& 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<SkSurface> render_surface;
|
||||
std::unique_ptr<flutter::EmbedderRenderTarget> 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<flutter::EmbedderRenderTarget>(
|
||||
backing_store, std::move(render_surface), collect_callback.Release());
|
||||
return render_target;
|
||||
}
|
||||
|
||||
static std::pair<std::unique_ptr<flutter::EmbedderExternalViewEmbedder>,
|
||||
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<impeller::AiksContext>& 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(
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -125,6 +125,7 @@ static FlutterBackingStoreConfig MakeBackingStoreConfig(
|
||||
// |ExternalViewEmbedder|
|
||||
void EmbedderExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> 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.";
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_EXTERNAL_VIEW_EMBEDDER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "flutter/flow/embedded_views.h"
|
||||
@ -31,6 +32,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
using CreateRenderTargetCallback =
|
||||
std::function<std::unique_ptr<EmbedderRenderTarget>(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
const FlutterBackingStoreConfig& config)>;
|
||||
using PresentCallback =
|
||||
std::function<bool(const std::vector<const FlutterLayer*>& layers)>;
|
||||
@ -95,6 +97,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
|
||||
@ -4,24 +4,17 @@
|
||||
|
||||
#include "flutter/shell/platform/embedder/embedder_render_target.h"
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
EmbedderRenderTarget::EmbedderRenderTarget(FlutterBackingStore backing_store,
|
||||
sk_sp<SkSurface> 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<SkSurface> EmbedderRenderTarget::GetRenderSurface() const {
|
||||
return render_surface_;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -5,12 +5,18 @@
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_H_
|
||||
|
||||
#include <memory>
|
||||
#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<SkSurface> 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<SkSurface> GetRenderSurface() const;
|
||||
virtual sk_sp<SkSurface> 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<impeller::AiksContext> 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<SkSurface> render_surface_;
|
||||
|
||||
fml::closure on_release_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderRenderTarget);
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -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<impeller::AiksContext> aiks_context,
|
||||
std::unique_ptr<impeller::RenderTarget> 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<SkSurface> EmbedderRenderTargetImpeller::GetSkiaSurface() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
impeller::RenderTarget* EmbedderRenderTargetImpeller::GetImpellerRenderTarget()
|
||||
const {
|
||||
return impeller_target_.get();
|
||||
}
|
||||
|
||||
std::shared_ptr<impeller::AiksContext>
|
||||
EmbedderRenderTargetImpeller::GetAiksContext() const {
|
||||
return aiks_context_;
|
||||
}
|
||||
|
||||
SkISize EmbedderRenderTargetImpeller::GetRenderTargetSize() const {
|
||||
auto size = impeller_target_->GetRenderTargetSize();
|
||||
return SkISize::Make(size.width, size.height);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -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<impeller::AiksContext> aiks_context,
|
||||
std::unique_ptr<impeller::RenderTarget> impeller_target,
|
||||
fml::closure on_release);
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
~EmbedderRenderTargetImpeller() override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
sk_sp<SkSurface> GetSkiaSurface() const override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
impeller::RenderTarget* GetImpellerRenderTarget() const override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
SkISize GetRenderTargetSize() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<impeller::AiksContext> aiks_context_;
|
||||
std::unique_ptr<impeller::RenderTarget> impeller_target_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderRenderTargetImpeller);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_IMPELLER_H_
|
||||
@ -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<SkSurface> 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<SkSurface> EmbedderRenderTargetSkia::GetSkiaSurface() const {
|
||||
return render_surface_;
|
||||
}
|
||||
|
||||
impeller::RenderTarget* EmbedderRenderTargetSkia::GetImpellerRenderTarget()
|
||||
const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<impeller::AiksContext>
|
||||
EmbedderRenderTargetSkia::GetAiksContext() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkISize EmbedderRenderTargetSkia::GetRenderTargetSize() const {
|
||||
return SkISize::Make(render_surface_->width(), render_surface_->height());
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -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<SkSurface> render_surface,
|
||||
fml::closure on_release);
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
~EmbedderRenderTargetSkia() override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
sk_sp<SkSurface> GetSkiaSurface() const override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
impeller::RenderTarget* GetImpellerRenderTarget() const override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
std::shared_ptr<impeller::AiksContext> GetAiksContext() const override;
|
||||
|
||||
// |EmbedderRenderTarget|
|
||||
SkISize GetRenderTargetSize() const override;
|
||||
|
||||
private:
|
||||
sk_sp<SkSurface> render_surface_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderRenderTargetSkia);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_RENDER_TARGET_SKIA_H_
|
||||
@ -10,4 +10,13 @@ EmbedderSurface::EmbedderSurface() = default;
|
||||
|
||||
EmbedderSurface::~EmbedderSurface() = default;
|
||||
|
||||
std::shared_ptr<impeller::Context> EmbedderSurface::CreateImpellerContext()
|
||||
const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrDirectContext> EmbedderSurface::CreateResourceContext() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_H_
|
||||
|
||||
#include <memory>
|
||||
#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<Surface> CreateGPUSurface() = 0;
|
||||
|
||||
virtual sk_sp<GrDirectContext> CreateResourceContext() const = 0;
|
||||
virtual std::shared_ptr<impeller::Context> CreateImpellerContext() const;
|
||||
|
||||
virtual sk_sp<GrDirectContext> CreateResourceContext() const;
|
||||
|
||||
private:
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderSurface);
|
||||
|
||||
@ -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 <memory>
|
||||
#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<bool(GPUMTLTextureInfo texture)> present; // required
|
||||
std::function<GPUMTLTextureInfo(const SkISize& frame_size)>
|
||||
get_texture; // required
|
||||
};
|
||||
|
||||
EmbedderSurfaceMetalImpeller(
|
||||
GPUMTLDeviceHandle device,
|
||||
GPUMTLCommandQueueHandle command_queue,
|
||||
MetalDispatchTable dispatch_table,
|
||||
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder);
|
||||
|
||||
~EmbedderSurfaceMetalImpeller() override;
|
||||
|
||||
private:
|
||||
bool valid_ = false;
|
||||
MetalDispatchTable metal_dispatch_table_;
|
||||
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder_;
|
||||
std::shared_ptr<impeller::Context> context_;
|
||||
std::shared_ptr<fml::ConcurrentMessageLoop> concurrent_loop_;
|
||||
|
||||
// |EmbedderSurface|
|
||||
bool IsValid() const override;
|
||||
|
||||
// |EmbedderSurface|
|
||||
std::unique_ptr<Surface> 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_
|
||||
@ -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 <memory>
|
||||
#include <utility>
|
||||
|
||||
#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<EmbedderExternalViewEmbedder> 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<std::shared_ptr<fml::Mapping>> shader_mappings = {
|
||||
std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_data,
|
||||
impeller_entity_shaders_length),
|
||||
std::make_shared<fml::NonOwnedMapping>(impeller_scene_shaders_data,
|
||||
impeller_scene_shaders_length),
|
||||
std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_data,
|
||||
impeller_modern_shaders_length),
|
||||
std::make_shared<fml::NonOwnedMapping>(impeller_framebuffer_blend_shaders_data,
|
||||
impeller_framebuffer_blend_shaders_length),
|
||||
};
|
||||
context_ = impeller::ContextMTL::Create(
|
||||
(id<MTLDevice>)device, // device
|
||||
(id<MTLCommandQueue>)command_queue, // command_queue
|
||||
shader_mappings, // shader_libraries_data
|
||||
concurrent_loop_->GetTaskRunner(), // worker_task_runner
|
||||
std::make_shared<fml::SyncSwitch>(false), // is_gpu_disabled_sync_switch
|
||||
"Impeller Library" // library_label
|
||||
);
|
||||
|
||||
valid_ = !!context_;
|
||||
}
|
||||
|
||||
EmbedderSurfaceMetalImpeller::~EmbedderSurfaceMetalImpeller() = default;
|
||||
|
||||
bool EmbedderSurfaceMetalImpeller::IsValid() const {
|
||||
return valid_;
|
||||
}
|
||||
|
||||
std::unique_ptr<Surface> EmbedderSurfaceMetalImpeller::CreateGPUSurface()
|
||||
IMPELLER_CA_METAL_LAYER_AVAILABLE {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const bool render_to_surface = !external_view_embedder_;
|
||||
auto surface = std::make_unique<GPUSurfaceMetalImpeller>(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
|
||||
@ -86,7 +86,7 @@ PlatformViewEmbedder::PlatformViewEmbedder(
|
||||
PlatformViewEmbedder::PlatformViewEmbedder(
|
||||
PlatformView::Delegate& delegate,
|
||||
const flutter::TaskRunners& task_runners,
|
||||
std::unique_ptr<EmbedderSurfaceMetal> embedder_surface,
|
||||
std::unique_ptr<EmbedderSurface> embedder_surface,
|
||||
PlatformDispatchTable platform_dispatch_table,
|
||||
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder)
|
||||
: PlatformView(delegate, task_runners),
|
||||
@ -157,6 +157,11 @@ PlatformViewEmbedder::CreateExternalViewEmbedder() {
|
||||
return external_view_embedder_;
|
||||
}
|
||||
|
||||
std::shared_ptr<impeller::Context> PlatformViewEmbedder::GetImpellerContext()
|
||||
const {
|
||||
return embedder_surface_->CreateImpellerContext();
|
||||
}
|
||||
|
||||
// |PlatformView|
|
||||
sk_sp<GrDirectContext> PlatformViewEmbedder::CreateResourceContext() const {
|
||||
if (embedder_surface_ == nullptr) {
|
||||
|
||||
@ -76,7 +76,7 @@ class PlatformViewEmbedder final : public PlatformView {
|
||||
PlatformViewEmbedder(
|
||||
PlatformView::Delegate& delegate,
|
||||
const flutter::TaskRunners& task_runners,
|
||||
std::unique_ptr<EmbedderSurfaceMetal> embedder_surface,
|
||||
std::unique_ptr<EmbedderSurface> embedder_surface,
|
||||
PlatformDispatchTable platform_dispatch_table,
|
||||
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder);
|
||||
#endif
|
||||
@ -118,6 +118,9 @@ class PlatformViewEmbedder final : public PlatformView {
|
||||
// |PlatformView|
|
||||
std::shared_ptr<ExternalViewEmbedder> CreateExternalViewEmbedder() override;
|
||||
|
||||
// |PlatformView|
|
||||
std::shared_ptr<impeller::Context> GetImpellerContext() const override;
|
||||
|
||||
// |PlatformView|
|
||||
sk_sp<GrDirectContext> CreateResourceContext() const override;
|
||||
|
||||
|
||||
@ -132,6 +132,7 @@ void FlatlandExternalViewEmbedder::EndFrame(
|
||||
|
||||
void FlatlandExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "FlatlandExternalViewEmbedder::SubmitFrame");
|
||||
std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
|
||||
|
||||
@ -87,6 +87,7 @@ class FlatlandExternalViewEmbedder final
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
|
||||
@ -231,6 +231,7 @@ void GfxExternalViewEmbedder::EndFrame(
|
||||
|
||||
void GfxExternalViewEmbedder::SubmitFrame(
|
||||
GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) {
|
||||
TRACE_EVENT0("flutter", "GfxExternalViewEmbedder::SubmitFrame");
|
||||
std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
|
||||
|
||||
@ -110,6 +110,7 @@ class GfxExternalViewEmbedder final : public flutter::ExternalViewEmbedder {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override;
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
|
||||
@ -54,6 +54,7 @@ class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
|
||||
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {}
|
||||
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override {}
|
||||
|
||||
void PrerollCompositeEmbeddedView(
|
||||
|
||||
@ -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<flutter::SurfaceFrame>(
|
||||
nullptr, std::move(framebuffer_info),
|
||||
[](const flutter::SurfaceFrame& surface_frame,
|
||||
flutter::DlCanvas* canvas) { return true; },
|
||||
frame_size));
|
||||
nullptr, nullptr,
|
||||
std::make_unique<flutter::SurfaceFrame>(
|
||||
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<flutter::SurfaceFrame>(
|
||||
nullptr, std::move(framebuffer_info),
|
||||
[](const flutter::SurfaceFrame& surface_frame,
|
||||
flutter::DlCanvas* canvas) { return true; },
|
||||
frame_size));
|
||||
nullptr, nullptr,
|
||||
std::make_unique<flutter::SurfaceFrame>(
|
||||
nullptr, std::move(framebuffer_info),
|
||||
[](const flutter::SurfaceFrame& surface_frame,
|
||||
flutter::DlCanvas* canvas) { return true; },
|
||||
frame_size));
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
@ -53,6 +53,7 @@ class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
|
||||
fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) override {}
|
||||
|
||||
void SubmitFrame(GrDirectContext* context,
|
||||
const std::shared_ptr<impeller::AiksContext>& aiks_context,
|
||||
std::unique_ptr<flutter::SurfaceFrame> frame) override {}
|
||||
|
||||
void PrerollCompositeEmbeddedView(
|
||||
|
||||
@ -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<flutter::SurfaceFrame>(
|
||||
nullptr, framebuffer_info,
|
||||
[](const flutter::SurfaceFrame& surface_frame,
|
||||
flutter::DlCanvas* canvas) { return true; },
|
||||
frame_size));
|
||||
nullptr, nullptr,
|
||||
std::make_unique<flutter::SurfaceFrame>(
|
||||
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<flutter::SurfaceFrame>(
|
||||
nullptr, framebuffer_info,
|
||||
[](const flutter::SurfaceFrame& surface_frame,
|
||||
flutter::DlCanvas* canvas) { return true; },
|
||||
frame_size));
|
||||
nullptr, nullptr,
|
||||
std::make_unique<flutter::SurfaceFrame>(
|
||||
nullptr, framebuffer_info,
|
||||
[](const flutter::SurfaceFrame& surface_frame,
|
||||
flutter::DlCanvas* canvas) { return true; },
|
||||
frame_size));
|
||||
}
|
||||
|
||||
FramePresentedInfo MakeFramePresentedInfoForOnePresent(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user