Flutter Engine
 
Loading...
Searching...
No Matches
impeller::SurfaceMTL Class Referencefinal

#include <surface_mtl.h>

Inheritance diagram for impeller::SurfaceMTL:
impeller::Surface

Public Member Functions

 ~SurfaceMTL () override
 
id< MTLDrawable > drawable () const
 
IRect coverage () const
 
void PresentWithTransaction (bool present_with_transaction)
 
bool PreparePresent () const
 Perform the final blit and trigger end of frame workloads.
 
bool Present () const override
 
void SetFrameBoundary (bool frame_boundary)
 
- Public Member Functions inherited from impeller::Surface
 Surface ()
 
 Surface (const RenderTarget &target_desc)
 
virtual ~Surface ()
 
const ISizeGetSize () const
 
bool IsValid () const
 
const RenderTargetGetRenderTarget () const
 

Static Public Member Functions

static id< CAMetalDrawable > GetMetalDrawableAndValidate (const std::shared_ptr< Context > &context, CAMetalLayer *layer)
 Wraps the current drawable of the given Metal layer to create a surface Impeller can render to. The surface must be created as late as possible and discarded immediately after rendering to it.
 
static std::unique_ptr< SurfaceMTLMakeFromMetalLayerDrawable (const std::shared_ptr< Context > &context, id< CAMetalDrawable > drawable, const std::shared_ptr< SwapchainTransientsMTL > &transients, std::optional< IRect > clip_rect=std::nullopt)
 
static std::unique_ptr< SurfaceMTLMakeFromTexture (const std::shared_ptr< Context > &context, id< MTLTexture > texture, const std::shared_ptr< SwapchainTransientsMTL > &transients, std::optional< IRect > clip_rect, id< CAMetalDrawable > drawable=nil)
 

Detailed Description

Definition at line 18 of file surface_mtl.h.

Constructor & Destructor Documentation

◆ ~SurfaceMTL()

impeller::SurfaceMTL::~SurfaceMTL ( )
overridedefault

Member Function Documentation

◆ coverage()

IRect impeller::SurfaceMTL::coverage ( ) const

Definition at line 212 of file surface_mtl.mm.

212 {
213 return IRect::MakeSize(resolve_texture_->GetSize());
214}
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150

References impeller::TRect< T >::MakeSize().

◆ drawable()

id< MTLDrawable > impeller::SurfaceMTL::drawable ( ) const
inline

Definition at line 59 of file surface_mtl.h.

59{ return drawable_; }

Referenced by MakeFromMetalLayerDrawable(), MakeFromTexture(), and Present().

◆ GetMetalDrawableAndValidate()

id< CAMetalDrawable > impeller::SurfaceMTL::GetMetalDrawableAndValidate ( const std::shared_ptr< Context > &  context,
CAMetalLayer *  layer 
)
static

Wraps the current drawable of the given Metal layer to create a surface Impeller can render to. The surface must be created as late as possible and discarded immediately after rendering to it.

Parameters
[in]contextThe context
[in]layerThe layer whose current drawable to wrap to create a surface.
Returns
A pointer to the wrapped surface or null.

Definition at line 29 of file surface_mtl.mm.

31 {
32 TRACE_EVENT0("impeller", "SurfaceMTL::WrapCurrentMetalLayerDrawable");
33
34 if (context == nullptr || !context->IsValid() || layer == nil) {
35 return nullptr;
36 }
37
38 id<CAMetalDrawable> current_drawable = nil;
39 {
40 TRACE_EVENT0("impeller", "WaitForNextDrawable");
41 current_drawable = [layer nextDrawable];
42 }
43
44 if (!current_drawable) {
45 VALIDATION_LOG << "Could not acquire current drawable.";
46 return nullptr;
47 }
48 return current_drawable;
49}
#define TRACE_EVENT0(category_group, name)
#define VALIDATION_LOG
Definition validation.h:91

References TRACE_EVENT0, and VALIDATION_LOG.

◆ MakeFromMetalLayerDrawable()

std::unique_ptr< SurfaceMTL > impeller::SurfaceMTL::MakeFromMetalLayerDrawable ( const std::shared_ptr< Context > &  context,
id< CAMetalDrawable >  drawable,
const std::shared_ptr< SwapchainTransientsMTL > &  transients,
std::optional< IRect clip_rect = std::nullopt 
)
static

Definition at line 113 of file surface_mtl.mm.

117 {
118 return SurfaceMTL::MakeFromTexture(context, drawable.texture, transients,
119 clip_rect, drawable);
120}
id< MTLDrawable > drawable() const
Definition surface_mtl.h:59
static std::unique_ptr< SurfaceMTL > MakeFromTexture(const std::shared_ptr< Context > &context, id< MTLTexture > texture, const std::shared_ptr< SwapchainTransientsMTL > &transients, std::optional< IRect > clip_rect, id< CAMetalDrawable > drawable=nil)

References drawable(), and MakeFromTexture().

◆ MakeFromTexture()

std::unique_ptr< SurfaceMTL > impeller::SurfaceMTL::MakeFromTexture ( const std::shared_ptr< Context > &  context,
id< MTLTexture >  texture,
const std::shared_ptr< SwapchainTransientsMTL > &  transients,
std::optional< IRect clip_rect,
id< CAMetalDrawable >  drawable = nil 
)
static

Definition at line 122 of file surface_mtl.mm.

127 {
128 bool partial_repaint_blit_required = ShouldPerformPartialRepaint(clip_rect);
129
130 // The returned render target is the texture that Impeller will render the
131 // root pass to. If partial repaint is in use, this may be a new texture which
132 // is smaller than the given MTLTexture.
133 auto render_target = WrapTextureWithRenderTarget(
134 transients, texture, partial_repaint_blit_required, clip_rect);
135 if (!render_target) {
136 return nullptr;
137 }
138
139 // If partial repainting, set a "source" texture. The presence of a source
140 // texture and clip rect instructs the surface to blit this texture to the
141 // destination texture.
142 auto source_texture = partial_repaint_blit_required
143 ? render_target->GetRenderTargetTexture()
144 : nullptr;
145
146 // The final "destination" texture is the texture that will be presented. In
147 // this case, it's always the given drawable.
148 std::shared_ptr<Texture> destination_texture;
149 if (partial_repaint_blit_required) {
150 // If blitting for partial repaint, we need to wrap the drawable. Simply
151 // reuse the texture descriptor that was already formed for the new render
152 // target, but override the size with the drawable's size.
153 auto destination_descriptor =
154 render_target->GetRenderTargetTexture()->GetTextureDescriptor();
155 destination_descriptor.size = {static_cast<ISize::Type>(texture.width),
156 static_cast<ISize::Type>(texture.height)};
157 destination_texture = TextureMTL::Wrapper(destination_descriptor, texture);
158 } else {
159 // When not partial repaint blit is needed, the render target texture _is_
160 // the drawable texture.
161 destination_texture = render_target->GetRenderTargetTexture();
162 }
163
164 return std::unique_ptr<SurfaceMTL>(new SurfaceMTL(
165 context, // context
166 *render_target, // target
167 render_target->GetRenderTargetTexture(), // resolve_texture
168 drawable, // drawable
169 source_texture, // source_texture
170 destination_texture, // destination_texture
171 partial_repaint_blit_required, // requires_blit
172 clip_rect // clip_rect
173 ));
174}
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
FlTexture * texture
static std::optional< RenderTarget > WrapTextureWithRenderTarget(const std::shared_ptr< SwapchainTransientsMTL > &transients, id< MTLTexture > texture, bool requires_blit, std::optional< IRect > clip_rect)

References drawable(), texture, impeller::TextureMTL::Wrapper(), and impeller::WrapTextureWithRenderTarget().

Referenced by MakeFromMetalLayerDrawable().

◆ PreparePresent()

bool impeller::SurfaceMTL::PreparePresent ( ) const

Perform the final blit and trigger end of frame workloads.

Definition at line 216 of file surface_mtl.mm.

216 {
217 auto context = context_.lock();
218 if (!context) {
219 return false;
220 }
221
222#ifdef IMPELLER_DEBUG
223 context->GetResourceAllocator()->DebugTraceMemoryStatistics();
224 if (frame_boundary_) {
225 ContextMTL::Cast(context.get())->GetCaptureManager()->FinishCapture();
226 }
227#endif // IMPELLER_DEBUG
228
229 if (requires_blit_) {
230 if (!(source_texture_ && destination_texture_)) {
231 return false;
232 }
233
234 auto blit_command_buffer = context->CreateCommandBuffer();
235 if (!blit_command_buffer) {
236 return false;
237 }
238 auto blit_pass = blit_command_buffer->CreateBlitPass();
239 if (!clip_rect_.has_value()) {
240 VALIDATION_LOG << "Missing clip rectangle.";
241 return false;
242 }
243 blit_pass->AddCopy(source_texture_, destination_texture_, clip_rect_,
244 clip_rect_->GetOrigin());
245 blit_pass->EncodeCommands();
246 if (!context->GetCommandQueue()->Submit({blit_command_buffer}).ok()) {
247 return false;
248 }
249 }
250#ifdef IMPELLER_DEBUG
251 ContextMTL::Cast(context.get())->GetGPUTracer()->MarkFrameEnd();
252#endif // IMPELLER_DEBUG
253 prepared_ = true;
254 return true;
255}
static ContextMTL & Cast(Context &base)
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::ContextMTL::CreateCommandBuffer(), and VALIDATION_LOG.

Referenced by Present().

◆ Present()

bool impeller::SurfaceMTL::Present ( ) const
overridevirtual

Reimplemented from impeller::Surface.

Definition at line 258 of file surface_mtl.mm.

258 {
259 if (!prepared_) {
261 }
262 auto context = context_.lock();
263 if (!context) {
264 return false;
265 }
266
267 if (drawable_) {
268 id<MTLCommandBuffer> command_buffer =
269 ContextMTL::Cast(context.get())
270 ->CreateMTLCommandBuffer("Present Waiter Command Buffer");
271
272 id<CAMetalDrawable> metal_drawable =
273 reinterpret_cast<id<CAMetalDrawable>>(drawable_);
274 if ([metal_drawable conformsToProtocol:@protocol(FlutterMetalDrawable)]) {
275 [(id<FlutterMetalDrawable>)metal_drawable
276 flutterPrepareForPresent:command_buffer];
277 }
278
279 // Intel iOS simulators do not seem to give backpressure on Metal drawable
280 // aquisition, which can result in Impeller running head of the GPU
281 // workload by dozens of frames. Slow this process down by blocking
282 // on submit until the last command buffer is at least scheduled.
283#if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
284 constexpr bool alwaysWaitForScheduling = true;
285#else
286 constexpr bool alwaysWaitForScheduling = false;
287#endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
288
289 // If the threads have been merged, or there is a pending frame capture,
290 // then block on cmd buffer scheduling to ensure that the
291 // transaction/capture work correctly.
292 if (present_with_transaction_ || [[NSThread currentThread] isMainThread] ||
293 [[MTLCaptureManager sharedCaptureManager] isCapturing] ||
294 alwaysWaitForScheduling) {
295 TRACE_EVENT0("flutter", "waitUntilScheduled");
296 [command_buffer commit];
297#if defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
298 [command_buffer waitUntilCompleted];
299#else
300 [command_buffer waitUntilScheduled];
301#endif // defined(FML_OS_IOS_SIMULATOR) && defined(FML_ARCH_CPU_X86_64)
302 [drawable_ present];
303 } else {
304 // The drawable may come from a FlutterMetalLayer, so it can't be
305 // presented through the command buffer.
306 id<CAMetalDrawable> drawable = drawable_;
307 [command_buffer addScheduledHandler:^(id<MTLCommandBuffer> buffer) {
308 [drawable present];
309 }];
310 [command_buffer commit];
311 }
312 }
313
314 return true;
315}
id< MTLCommandBuffer > CreateMTLCommandBuffer(const std::string &label) const
bool PreparePresent() const
Perform the final blit and trigger end of frame workloads.
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::ContextMTL::CreateMTLCommandBuffer(), drawable(), PreparePresent(), and TRACE_EVENT0.

◆ PresentWithTransaction()

void impeller::SurfaceMTL::PresentWithTransaction ( bool  present_with_transaction)
inline

Mark this surface as presenting with a transaction.

If true, [Present] will block on the scheduling of a command buffer.

Definition at line 67 of file surface_mtl.h.

67 {
68 present_with_transaction_ = present_with_transaction;
69 }

◆ SetFrameBoundary()

void impeller::SurfaceMTL::SetFrameBoundary ( bool  frame_boundary)
inline

Definition at line 77 of file surface_mtl.h.

77 {
78 frame_boundary_ = frame_boundary;
79 }

The documentation for this class was generated from the following files: