Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
embedder.cc File Reference
#include <cstring>
#include <iostream>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "impeller/base/flags.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/closure.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/native_library.h"
#include "flutter/fml/status_or.h"
#include "flutter/fml/thread.h"
#include "third_party/dart/runtime/bin/elf_loader.h"
#include "third_party/dart/runtime/include/dart_native_api.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GpuTypes.h"
#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
#include "flutter/assets/directory_asset_bundle.h"
#include "flutter/common/graphics/persistent_cache.h"
#include "flutter/common/task_runners.h"
#include "flutter/fml/command_line.h"
#include "flutter/fml/file.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/embedder_engine.h"
#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_semantics_update.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"
#include "flutter/shell/platform/embedder/pixel_formats.h"
#include "flutter/shell/platform/embedder/platform_view_embedder.h"
#include "rapidjson/rapidjson.h"
#include "rapidjson/writer.h"

Go to the source code of this file.

Classes

struct  _FlutterPlatformMessageResponseHandle
 
struct  LoadedElfDeleter
 
struct  _FlutterEngineAOTData
 

Macros

#define FML_USED_ON_EMBEDDER
 
#define RAPIDJSON_HAS_STDSTRING   1
 
#define FLUTTER_EXPORT   __attribute__((visibility("default")))
 
#define LOG_EMBEDDER_ERROR(code, reason)    LogEmbedderError(code, reason, #code, __FUNCTION__, __FILE__, __LINE__)
 
#define SET_PROC(member, function)
 

Typedefs

using UniqueLoadedElf = std::unique_ptr< Dart_LoadedElf, LoadedElfDeleter >
 

Functions

static FlutterEngineResult LogEmbedderError (FlutterEngineResult code, const char *reason, const char *code_name, const char *function, const char *file, int line)
 
static bool IsOpenGLRendererConfigValid (const FlutterRendererConfig *config)
 
static bool IsSoftwareRendererConfigValid (const FlutterRendererConfig *config)
 
static bool IsMetalRendererConfigValid (const FlutterRendererConfig *config)
 
static bool IsVulkanRendererConfigValid (const FlutterRendererConfig *config)
 
static bool IsRendererValid (const FlutterRendererConfig *config)
 
static flutter::Shell::CreateCallback< flutter::PlatformViewInferOpenGLPlatformViewCreationCallback (const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
 
static flutter::Shell::CreateCallback< flutter::PlatformViewInferMetalPlatformViewCreationCallback (const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
 
static flutter::Shell::CreateCallback< flutter::PlatformViewInferVulkanPlatformViewCreationCallback (const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
 
static flutter::Shell::CreateCallback< flutter::PlatformViewInferSoftwarePlatformViewCreationCallback (const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder)
 
static flutter::Shell::CreateCallback< flutter::PlatformViewInferPlatformViewCreationCallback (const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLTexture *texture)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLFramebuffer *framebuffer)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLSurface *surface)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterSoftwareBackingStore *software)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterSoftwareBackingStore2 *software)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterMetalBackingStore *metal)
 
static std::unique_ptr< flutter::EmbedderRenderTargetMakeRenderTargetFromBackingStoreImpeller (FlutterBackingStore backing_store, const fml::closure &on_release, const std::shared_ptr< impeller::AiksContext > &aiks_context, const FlutterBackingStoreConfig &config, const FlutterOpenGLFramebuffer *framebuffer)
 
static std::unique_ptr< flutter::EmbedderRenderTargetMakeRenderTargetFromBackingStoreImpeller (FlutterBackingStore backing_store, const fml::closure &on_release, const std::shared_ptr< impeller::AiksContext > &aiks_context, const FlutterBackingStoreConfig &config, const FlutterMetalBackingStore *metal)
 
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterVulkanBackingStore *vulkan)
 
static std::unique_ptr< flutter::EmbedderRenderTargetMakeRenderTargetFromSkSurface (FlutterBackingStore backing_store, sk_sp< SkSurface > skia_surface, fml::closure on_release, flutter::EmbedderRenderTarget::MakeOrClearCurrentCallback on_make_current, flutter::EmbedderRenderTarget::MakeOrClearCurrentCallback on_clear_current)
 
static std::unique_ptr< flutter::EmbedderRenderTargetMakeRenderTargetFromSkSurface (FlutterBackingStore backing_store, sk_sp< SkSurface > skia_surface, fml::closure on_release)
 
static std::unique_ptr< flutter::EmbedderRenderTargetCreateEmbedderRenderTarget (const FlutterCompositor *compositor, const FlutterBackingStoreConfig &config, GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, bool enable_impeller)
 
static fml::StatusOr< std::unique_ptr< flutter::EmbedderExternalViewEmbedder > > InferExternalViewEmbedderFromArgs (const FlutterCompositor *compositor, bool enable_impeller)
 
static std::variant< flutter::ViewportMetrics, std::string > MakeViewportMetricsFromWindowMetrics (const FlutterWindowMetricsEvent *flutter_metrics)
 
FlutterEngineResult FlutterEngineCreateAOTData (const FlutterEngineAOTDataSource *source, FlutterEngineAOTData *data_out)
 Creates the necessary data structures to launch a Flutter Dart application in AOT mode. The data may only be collected after all FlutterEngine instances launched using this data have been terminated.
 
FlutterEngineResult FlutterEngineCollectAOTData (FlutterEngineAOTData data)
 Collects the AOT data.
 
void PopulateJITSnapshotMappingCallbacks (const FlutterProjectArgs *args, flutter::Settings &settings)
 
void PopulateAOTSnapshotMappingCallbacks (const FlutterProjectArgs *args, flutter::Settings &settings)
 
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV1 (FlutterUpdateSemanticsNodeCallback update_semantics_node_callback, FlutterUpdateSemanticsCustomActionCallback update_semantics_custom_action_callback, void *user_data)
 
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV2 (FlutterUpdateSemanticsCallback update_semantics_callback, void *user_data)
 
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV3 (FlutterUpdateSemanticsCallback2 update_semantics_callback, void *user_data)
 
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallback (const FlutterProjectArgs *args, void *user_data)
 
FlutterEngineResult FlutterEngineRun (size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
 Initialize and run a Flutter engine instance and return a handle to it. This is a convenience method for the pair of calls to FlutterEngineInitialize and FlutterEngineRunInitialized.
 
FlutterEngineResult FlutterEngineInitialize (size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
 Initialize a Flutter engine instance. This does not run the Flutter application code till the FlutterEngineRunInitialized call is made. Besides Flutter application code, no tasks are scheduled on embedder managed task runners either. This allows embedders providing custom task runners to the Flutter engine to obtain a handle to the Flutter engine before the engine can post tasks on these task runners.
 
FlutterEngineResult FlutterEngineRunInitialized (FLUTTER_API_SYMBOL(FlutterEngine) engine)
 Runs an initialized engine instance. An engine can be initialized via FlutterEngineInitialize. An initialized instance can only be run once. During and after this call, custom task runners supplied by the embedder are expected to start servicing tasks.
 
FLUTTER_EXPORT FlutterEngineResult FlutterEngineAddView (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterAddViewInfo *info)
 Adds a view.
 
FLUTTER_EXPORT FlutterEngineResult FlutterEngineRemoveView (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterRemoveViewInfo *info)
 Removes a view.
 
FlutterEngineResult FlutterEngineSendViewFocusEvent (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterViewFocusEvent *event)
 Notifies the engine that platform view focus state has changed.
 
FLUTTER_EXPORT FlutterEngineResult FlutterEngineDeinitialize (FLUTTER_API_SYMBOL(FlutterEngine) engine)
 Stops running the Flutter engine instance. After this call, the embedder is also guaranteed that no more calls to post tasks onto custom task runners specified by the embedder are made. The Flutter engine handle still needs to be collected via a call to FlutterEngineShutdown.
 
FlutterEngineResult FlutterEngineShutdown (FLUTTER_API_SYMBOL(FlutterEngine) engine)
 Shuts down a Flutter engine instance. The engine handle is no longer valid for any calls in the embedder API after this point. Making additional calls with this handle is undefined behavior.
 
FlutterEngineResult FlutterEngineSendWindowMetricsEvent (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
 
flutter::PointerData::Change ToPointerDataChange (FlutterPointerPhase phase)
 
flutter::PointerData::DeviceKind ToPointerDataKind (FlutterPointerDeviceKind device_kind)
 
flutter::PointerData::SignalKind ToPointerDataSignalKind (FlutterPointerSignalKind kind)
 
int64_t PointerDataButtonsForLegacyEvent (flutter::PointerData::Change change)
 
FlutterEngineResult FlutterEngineSendPointerEvent (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
 
static flutter::KeyEventType MapKeyEventType (FlutterKeyEventType event_kind)
 
static flutter::KeyEventDeviceType MapKeyEventDeviceType (FlutterKeyEventDeviceType event_kind)
 
static FlutterEngineResult InternalSendPlatformMessage (FLUTTER_API_SYMBOL(FlutterEngine) engine, const char *channel, const uint8_t *data, size_t size, FlutterDataCallback data_callback, void *user_data)
 
FlutterEngineResult FlutterEngineSendKeyEvent (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterKeyEvent *event, FlutterKeyEventCallback callback, void *user_data)
 Sends a key event to the engine. The framework will decide whether to handle this event in a synchronous fashion, although due to technical limitation, the result is always reported asynchronously. The callback is guaranteed to be called exactly once.
 
FlutterEngineResult FlutterEngineSendPlatformMessage (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
 
FlutterEngineResult FlutterPlatformMessageCreateResponseHandle (FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterDataCallback data_callback, void *user_data, FlutterPlatformMessageResponseHandle **response_out)
 Creates a platform message response handle that allows the embedder to set a native callback for a response to a message. This handle may be set on the response_handle field of any FlutterPlatformMessage sent to the engine.
 
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle (FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
 Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
 
FlutterEngineResult FlutterEngineSendPlatformMessageResponse (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
 Send a response from the native side to a platform message from the Dart Flutter application.
 
FlutterEngineResult __FlutterEngineFlushPendingTasksNow ()
 This API is only meant to be used by platforms that need to flush tasks on a message loop not controlled by the Flutter engine.
 
FlutterEngineResult FlutterEngineRegisterExternalTexture (FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
 Register an external texture with a unique (per engine) identifier. Only rendering backends that support external textures accept external texture registrations. After the external texture is registered, the application can mark that a frame is available by calling FlutterEngineMarkExternalTextureFrameAvailable.
 
FlutterEngineResult FlutterEngineUnregisterExternalTexture (FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
 Unregister a previous texture registration.
 
FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable (FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
 Mark that a new texture frame is available for a given texture identifier.
 
FlutterEngineResult FlutterEngineUpdateSemanticsEnabled (FLUTTER_API_SYMBOL(FlutterEngine) engine, bool enabled)
 Enable or disable accessibility semantics.
 
FlutterEngineResult FlutterEngineUpdateAccessibilityFeatures (FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterAccessibilityFeature flags)
 Sets additional accessibility features.
 
FlutterEngineResult FlutterEngineDispatchSemanticsAction (FLUTTER_API_SYMBOL(FlutterEngine) engine, uint64_t node_id, FlutterSemanticsAction action, const uint8_t *data, size_t data_length)
 Dispatch a semantics action to the specified semantics node in the implicit view.
 
FlutterEngineResult FlutterEngineSendSemanticsAction (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterSendSemanticsActionInfo *info)
 Dispatch a semantics action to the specified semantics node within a specific view.
 
FlutterEngineResult FlutterEngineOnVsync (FLUTTER_API_SYMBOL(FlutterEngine) engine, intptr_t baton, uint64_t frame_start_time_nanos, uint64_t frame_target_time_nanos)
 Notify the engine that a vsync event occurred. A baton passed to the platform via the vsync callback must be returned. This call must be made on the thread on which the call to FlutterEngineRun was made.
 
FlutterEngineResult FlutterEngineReloadSystemFonts (FLUTTER_API_SYMBOL(FlutterEngine) engine)
 Reloads the system fonts in engine.
 
void FlutterEngineTraceEventDurationBegin (const char *name)
 A profiling utility. Logs a trace duration begin event to the timeline. If the timeline is unavailable or disabled, this has no effect. Must be balanced with an duration end event (via FlutterEngineTraceEventDurationEnd) with the same name on the same thread. Can be called on any thread. Strings passed into the function will NOT be copied when added to the timeline. Only string literals may be passed in.
 
void FlutterEngineTraceEventDurationEnd (const char *name)
 A profiling utility. Logs a trace duration end event to the timeline. If the timeline is unavailable or disabled, this has no effect. This call must be preceded by a trace duration begin call (via FlutterEngineTraceEventDurationBegin) with the same name on the same thread. Can be called on any thread. Strings passed into the function will NOT be copied when added to the timeline. Only string literals may be passed in.
 
void FlutterEngineTraceEventInstant (const char *name)
 A profiling utility. Logs a trace duration instant event to the timeline. If the timeline is unavailable or disabled, this has no effect. Can be called on any thread. Strings passed into the function will NOT be copied when added to the timeline. Only string literals may be passed in.
 
FlutterEngineResult FlutterEnginePostRenderThreadTask (FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, void *baton)
 Posts a task onto the Flutter render thread. Typically, this may be called from any thread as long as a FlutterEngineShutdown on the specific engine has not already been initiated.
 
uint64_t FlutterEngineGetCurrentTime ()
 Get the current time in nanoseconds from the clock used by the flutter engine. This is the system monotonic clock.
 
FlutterEngineResult FlutterEngineRunTask (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterTask *task)
 Inform the engine to run the specified task. This task has been given to the embedder via the FlutterTaskRunnerDescription.post_task_callback. This call must only be made at the target time specified in that callback. Running the task before that time is undefined behavior.
 
static bool DispatchJSONPlatformMessage (FLUTTER_API_SYMBOL(FlutterEngine) engine, const rapidjson::Document &document, const std::string &channel_name)
 
FlutterEngineResult FlutterEngineUpdateLocales (FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterLocale **locales, size_t locales_count)
 Notify a running engine instance that the locale has been updated. The preferred locale must be the first item in the list of locales supplied. The other entries will be used as a fallback.
 
bool FlutterEngineRunsAOTCompiledDartCode (void)
 Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading restrictions.
 
FlutterEngineResult FlutterEnginePostDartObject (FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterEngineDartPort port, const FlutterEngineDartObject *object)
 Posts a Dart object to specified send port. The corresponding receive port for send port can be in any isolate running in the VM. This isolate can also be the root isolate for an unrelated engine. The engine parameter is necessary only to ensure the call is not made when no engine (and hence no VM) is running.
 
FlutterEngineResult FlutterEngineNotifyLowMemoryWarning (FLUTTER_API_SYMBOL(FlutterEngine) raw_engine)
 Posts a low memory notification to a running engine instance. The engine will do its best to release non-critical resources in response. It is not guaranteed that the resource would have been collected by the time this call returns however. The notification is posted to engine subsystems that may be operating on other threads.
 
FlutterEngineResult FlutterEnginePostCallbackOnAllNativeThreads (FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterNativeThreadCallback callback, void *user_data)
 Schedule a callback to be run on all engine managed threads. The engine will attempt to service this callback the next time the message loop for each managed thread is idle. Since the engine manages the entire lifecycle of multiple threads, there is no opportunity for the embedders to finely tune the priorities of threads directly, or, perform other thread specific configuration (for example, setting thread names for tracing). This callback gives embedders a chance to affect such tuning.
 
FlutterEngineResult FlutterEngineNotifyDisplayUpdate (FLUTTER_API_SYMBOL(FlutterEngine) raw_engine, const FlutterEngineDisplaysUpdateType update_type, const FlutterEngineDisplay *embedder_displays, size_t display_count)
 Posts updates corresponding to display changes to a running engine instance.
 
FlutterEngineResult FlutterEngineScheduleFrame (FLUTTER_API_SYMBOL(FlutterEngine) engine)
 Schedule a new frame to redraw the content.
 
FlutterEngineResult FlutterEngineSetNextFrameCallback (FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, void *user_data)
 Schedule a callback to be called after the next frame is drawn. This must be called from the platform thread. The callback is executed only once from the raster thread; embedders must re-thread if necessary. Performing blocking calls in this callback may introduce application jank.
 
FlutterEngineResult FlutterEngineGetProcAddresses (FlutterEngineProcTable *table)
 Gets the table of engine function pointers.
 

Variables

const uint8_t kPlatformStrongDill []
 
const intptr_t kPlatformStrongDillSize
 
const int32_t kFlutterSemanticsNodeIdBatchEnd = -1
 
const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1
 
static constexpr FlutterViewId kFlutterImplicitViewId = 0
 
const char * kFlutterKeyDataChannel = "flutter/keydata"
 

Macro Definition Documentation

◆ FLUTTER_EXPORT

#define FLUTTER_EXPORT   __attribute__((visibility("default")))

Definition at line 34 of file embedder.cc.

◆ FML_USED_ON_EMBEDDER

#define FML_USED_ON_EMBEDDER

Definition at line 5 of file embedder.cc.

◆ LOG_EMBEDDER_ERROR

#define LOG_EMBEDDER_ERROR (   code,
  reason 
)     LogEmbedderError(code, reason, #code, __FUNCTION__, __FILE__, __LINE__)

Definition at line 157 of file embedder.cc.

159 {
160 if (config->type != kOpenGL) {
161 return false;
162 }
163
164 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
165
166 if (!SAFE_EXISTS(open_gl_config, make_current) ||
167 !SAFE_EXISTS(open_gl_config, clear_current) ||
168 !SAFE_EXISTS_ONE_OF(open_gl_config, fbo_callback,
169 fbo_with_frame_info_callback) ||
170 !SAFE_EXISTS_ONE_OF(open_gl_config, present, present_with_info)) {
171 return false;
172 }
173
174 return true;
175}
176
177static bool IsSoftwareRendererConfigValid(const FlutterRendererConfig* config) {
178 if (config->type != kSoftware) {
179 return false;
180 }
181
182 const FlutterSoftwareRendererConfig* software_config = &config->software;
183
184 if (SAFE_ACCESS(software_config, surface_present_callback, nullptr) ==
185 nullptr) {
186 return false;
187 }
188
189 return true;
190}
191
192static bool IsMetalRendererConfigValid(const FlutterRendererConfig* config) {
193 if (config->type != kMetal) {
194 return false;
195 }
196
197 const FlutterMetalRendererConfig* metal_config = &config->metal;
198
199 bool device = SAFE_ACCESS(metal_config, device, nullptr);
200 bool command_queue =
201 SAFE_ACCESS(metal_config, present_command_queue, nullptr);
202
203 bool present = SAFE_ACCESS(metal_config, present_drawable_callback, nullptr);
204 bool get_texture =
205 SAFE_ACCESS(metal_config, get_next_drawable_callback, nullptr);
206
207 return device && command_queue && present && get_texture;
208}
209
210static bool IsVulkanRendererConfigValid(const FlutterRendererConfig* config) {
211 if (config->type != kVulkan) {
212 return false;
213 }
214
215 const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan;
216
217 if (!SAFE_EXISTS(vulkan_config, instance) ||
218 !SAFE_EXISTS(vulkan_config, physical_device) ||
219 !SAFE_EXISTS(vulkan_config, device) ||
220 !SAFE_EXISTS(vulkan_config, queue) ||
221 !SAFE_EXISTS(vulkan_config, get_instance_proc_address_callback) ||
222 !SAFE_EXISTS(vulkan_config, get_next_image_callback) ||
223 !SAFE_EXISTS(vulkan_config, present_image_callback)) {
224 return false;
225 }
226
227 return true;
228}
229
230static bool IsRendererValid(const FlutterRendererConfig* config) {
231 if (config == nullptr) {
232 return false;
233 }
234
235 switch (config->type) {
236 case kOpenGL:
237 return IsOpenGLRendererConfigValid(config);
238 case kSoftware:
239 return IsSoftwareRendererConfigValid(config);
240 case kMetal:
241 return IsMetalRendererConfigValid(config);
242 case kVulkan:
243 return IsVulkanRendererConfigValid(config);
244 default:
245 return false;
246 }
247
248 return false;
249}
250
251#if FML_OS_LINUX || FML_OS_WIN
252static void* DefaultGLProcResolver(const char* name) {
253 static fml::RefPtr<fml::NativeLibrary> proc_library =
254#if FML_OS_LINUX
256#elif FML_OS_WIN // FML_OS_LINUX
257 fml::NativeLibrary::Create("opengl32.dll");
258#endif // FML_OS_WIN
259 return static_cast<void*>(
260 const_cast<uint8_t*>(proc_library->ResolveSymbol(name)));
261}
262#endif // FML_OS_LINUX || FML_OS_WIN
263
264#ifdef SHELL_ENABLE_GL
265// Auxiliary function used to translate rectangles of type SkIRect to
266// FlutterRect.
267static FlutterRect DlIRectToFlutterRect(const flutter::DlIRect& dl_rect) {
268 FlutterRect flutter_rect = {static_cast<double>(dl_rect.GetLeft()),
269 static_cast<double>(dl_rect.GetTop()),
270 static_cast<double>(dl_rect.GetRight()),
271 static_cast<double>(dl_rect.GetBottom())};
272 return flutter_rect;
273}
274
275// Auxiliary function used to translate rectangles of type FlutterRect to
276// SkIRect.
277static const flutter::DlIRect FlutterRectToDlIRect(FlutterRect flutter_rect) {
278 return flutter::DlIRect::MakeLTRB(static_cast<int32_t>(flutter_rect.left),
279 static_cast<int32_t>(flutter_rect.top),
280 static_cast<int32_t>(flutter_rect.right),
281 static_cast<int32_t>(flutter_rect.bottom));
282}
283
284// We need GL_BGRA8_EXT for creating SkSurfaces from FlutterOpenGLSurfaces
285// below.
286#ifndef GL_BGRA8_EXT
287#define GL_BGRA8_EXT 0x93A1
288#endif
289
290static std::optional<SkColorType> FlutterFormatToSkColorType(uint32_t format) {
291 switch (format) {
292 case GL_BGRA8_EXT:
293 return kBGRA_8888_SkColorType;
294 case GL_RGBA8:
295 return kRGBA_8888_SkColorType;
296 default:
297 FML_LOG(ERROR) << "Cannot convert format " << format
298 << " to SkColorType.";
299 return std::nullopt;
300 }
301}
302
303#endif
304
307 const FlutterRendererConfig* config,
308 void* user_data,
310 platform_dispatch_table,
311 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
312 external_view_embedder,
313 bool enable_impeller,
314 impeller::Flags impeller_flags) {
315#ifdef SHELL_ENABLE_GL
316 if (config->type != kOpenGL) {
317 return nullptr;
318 }
319
320 auto gl_make_current = [ptr = config->open_gl.make_current,
321 user_data]() -> bool { return ptr(user_data); };
322
323 auto gl_clear_current = [ptr = config->open_gl.clear_current,
324 user_data]() -> bool { return ptr(user_data); };
325
326 auto gl_present =
327 [present = config->open_gl.present,
328 present_with_info = config->open_gl.present_with_info,
329 user_data](flutter::GLPresentInfo gl_present_info) -> bool {
330 if (present) {
331 return present(user_data);
332 } else {
333 // Format the frame and buffer damages accordingly. Note that, since the
334 // current compute damage algorithm only returns one rectangle for damage
335 // we are assuming the number of rectangles provided in frame and buffer
336 // damage are always 1. Once the function that computes damage implements
337 // support for multiple damage rectangles, GLPresentInfo should also
338 // contain the number of damage rectangles.
339
340 std::optional<FlutterRect> frame_damage_rect;
341 if (gl_present_info.frame_damage) {
342 frame_damage_rect =
343 DlIRectToFlutterRect(*(gl_present_info.frame_damage));
344 }
345 std::optional<FlutterRect> buffer_damage_rect;
346 if (gl_present_info.buffer_damage) {
347 buffer_damage_rect =
348 DlIRectToFlutterRect(*(gl_present_info.buffer_damage));
349 }
350
351 FlutterDamage frame_damage{
352 .struct_size = sizeof(FlutterDamage),
353 .num_rects = frame_damage_rect ? size_t{1} : size_t{0},
354 .damage = frame_damage_rect ? &frame_damage_rect.value() : nullptr,
355 };
356 FlutterDamage buffer_damage{
357 .struct_size = sizeof(FlutterDamage),
358 .num_rects = buffer_damage_rect ? size_t{1} : size_t{0},
359 .damage = buffer_damage_rect ? &buffer_damage_rect.value() : nullptr,
360 };
361
362 // Construct the present information concerning the frame being rendered.
363 FlutterPresentInfo present_info = {
365 .fbo_id = gl_present_info.fbo_id,
366 .frame_damage = frame_damage,
367 .buffer_damage = buffer_damage,
368 };
369
370 return present_with_info(user_data, &present_info);
371 }
372 };
373
374 auto gl_fbo_callback =
375 [fbo_callback = config->open_gl.fbo_callback,
376 fbo_with_frame_info_callback =
378 user_data](flutter::GLFrameInfo gl_frame_info) -> intptr_t {
379 if (fbo_callback) {
380 return fbo_callback(user_data);
381 } else {
382 FlutterFrameInfo frame_info = {};
383 frame_info.struct_size = sizeof(FlutterFrameInfo);
384 frame_info.size = {gl_frame_info.width, gl_frame_info.height};
385 return fbo_with_frame_info_callback(user_data, &frame_info);
386 }
387 };
388
389 auto gl_populate_existing_damage =
390 [populate_existing_damage = config->open_gl.populate_existing_damage,
391 user_data](intptr_t id) -> flutter::GLFBOInfo {
392 // If no populate_existing_damage was provided, disable partial
393 // repaint.
394 if (!populate_existing_damage) {
395 return flutter::GLFBOInfo{
396 .fbo_id = static_cast<uint32_t>(id),
397 .existing_damage = std::nullopt,
398 };
399 }
400
401 // Given the FBO's ID, get its existing damage.
402 FlutterDamage existing_damage;
403 populate_existing_damage(user_data, id, &existing_damage);
404
405 std::optional<flutter::DlIRect> existing_damage_rect = std::nullopt;
406
407 // Verify that at least one damage rectangle was provided.
408 if (existing_damage.num_rects <= 0 || existing_damage.damage == nullptr) {
409 FML_LOG(INFO) << "No damage was provided. Forcing full repaint.";
410 } else {
411 existing_damage_rect = flutter::DlIRect();
412 for (size_t i = 0; i < existing_damage.num_rects; i++) {
413 existing_damage_rect = existing_damage_rect->Union(
414 FlutterRectToDlIRect(existing_damage.damage[i]));
415 }
416 }
417
418 // Pass the information about this FBO to the rendering backend.
419 return flutter::GLFBOInfo{
420 .fbo_id = static_cast<uint32_t>(id),
421 .existing_damage = existing_damage_rect,
422 };
423 };
424
425 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
426 std::function<bool()> gl_make_resource_current_callback = nullptr;
427 if (SAFE_ACCESS(open_gl_config, make_resource_current, nullptr) != nullptr) {
428 gl_make_resource_current_callback =
429 [ptr = config->open_gl.make_resource_current, user_data]() {
430 return ptr(user_data);
431 };
432 }
433
434 std::function<flutter::DlMatrix(void)> gl_surface_transformation_callback =
435 nullptr;
436 if (SAFE_ACCESS(open_gl_config, surface_transformation, nullptr) != nullptr) {
437 gl_surface_transformation_callback =
438 [ptr = config->open_gl.surface_transformation, user_data]() {
439 FlutterTransformation transformation = ptr(user_data);
440 // clang-format off
441 return flutter::DlMatrix(
442 transformation.scaleX, transformation.skewY, 0.0f, transformation.pers0,
443 transformation.skewX, transformation.scaleY, 0.0f, transformation.pers1,
444 0.0f, 0.0f, 1.0f, 0.0f,
445 transformation.transX, transformation.transY, 0.0f, transformation.pers2
446 );
447 // clang-format on
448 };
449
450 // If there is an external view embedder, ask it to apply the surface
451 // transformation to its surfaces as well.
452 if (external_view_embedder) {
453 external_view_embedder->SetSurfaceTransformationCallback(
454 gl_surface_transformation_callback);
455 }
456 }
457
458 flutter::GPUSurfaceGLDelegate::GLProcResolver gl_proc_resolver = nullptr;
459 if (SAFE_ACCESS(open_gl_config, gl_proc_resolver, nullptr) != nullptr) {
460 gl_proc_resolver = [ptr = config->open_gl.gl_proc_resolver,
461 user_data](const char* gl_proc_name) {
462 return ptr(user_data, gl_proc_name);
463 };
464 } else {
465#if FML_OS_LINUX || FML_OS_WIN
466 gl_proc_resolver = DefaultGLProcResolver;
467#endif // FML_OS_LINUX || FML_OS_WIN
468 }
469
470 bool fbo_reset_after_present =
471 SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false);
472
474 gl_make_current, // gl_make_current_callback
475 gl_clear_current, // gl_clear_current_callback
476 gl_present, // gl_present_callback
477 gl_fbo_callback, // gl_fbo_callback
478 gl_make_resource_current_callback, // gl_make_resource_current_callback
479 gl_surface_transformation_callback, // gl_surface_transformation_callback
480 gl_proc_resolver, // gl_proc_resolver
481 gl_populate_existing_damage, // gl_populate_existing_damage
482 };
483
484 return fml::MakeCopyable(
485 [gl_dispatch_table, fbo_reset_after_present, platform_dispatch_table,
486 enable_impeller, impeller_flags,
487 external_view_embedder =
488 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
489 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
490 std::move(external_view_embedder);
491 if (enable_impeller) {
492 return std::make_unique<flutter::PlatformViewEmbedder>(
493 shell, // delegate
494 shell.GetTaskRunners(), // task runners
495 std::make_unique<flutter::EmbedderSurfaceGLImpeller>(
496 gl_dispatch_table, fbo_reset_after_present, view_embedder,
497 impeller_flags), // embedder_surface
498 platform_dispatch_table, // embedder platform dispatch table
499 view_embedder // external view embedder
500 );
501 }
502 return std::make_unique<flutter::PlatformViewEmbedder>(
503 shell, // delegate
504 shell.GetTaskRunners(), // task runners
505 std::make_unique<flutter::EmbedderSurfaceGLSkia>(
506 gl_dispatch_table, fbo_reset_after_present,
507 view_embedder), // embedder_surface
508 platform_dispatch_table, // embedder platform dispatch table
509 view_embedder // external view embedder
510 );
511 });
512#else // SHELL_ENABLE_GL
513 FML_LOG(ERROR) << "This Flutter Engine does not support OpenGL rendering.";
514 return nullptr;
515#endif // SHELL_ENABLE_GL
516}
517
520 const FlutterRendererConfig* config,
521 void* user_data,
523 platform_dispatch_table,
524 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
525 external_view_embedder,
526 bool enable_impeller,
527 impeller::Flags impeller_flags) {
528 if (config->type != kMetal) {
529 return nullptr;
530 }
531
532#ifdef SHELL_ENABLE_METAL
533 std::function<bool(flutter::GPUMTLTextureInfo texture)> metal_present =
534 [ptr = config->metal.present_drawable_callback,
536 FlutterMetalTexture embedder_texture;
537 embedder_texture.struct_size = sizeof(FlutterMetalTexture);
538 embedder_texture.texture = texture.texture;
539 embedder_texture.texture_id = texture.texture_id;
540 embedder_texture.user_data = texture.destruction_context;
541 embedder_texture.destruction_callback = texture.destruction_callback;
542 return ptr(user_data, &embedder_texture);
543 };
544 auto metal_get_texture =
546 const flutter::DlISize& frame_size) -> flutter::GPUMTLTextureInfo {
547 FlutterFrameInfo frame_info = {};
548 frame_info.struct_size = sizeof(FlutterFrameInfo);
549 frame_info.size = {static_cast<uint32_t>(frame_size.width),
550 static_cast<uint32_t>(frame_size.height)};
551 flutter::GPUMTLTextureInfo texture_info;
552
553 FlutterMetalTexture metal_texture = ptr(user_data, &frame_info);
554 texture_info.texture_id = metal_texture.texture_id;
555 texture_info.texture = metal_texture.texture;
556 texture_info.destruction_callback = metal_texture.destruction_callback;
557 texture_info.destruction_context = metal_texture.user_data;
558 return texture_info;
559 };
560
561 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
562 std::move(external_view_embedder);
563
564 // The static leak checker gets confused by the use of fml::MakeCopyable.
565 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
566 return fml::MakeCopyable([config, metal_present, metal_get_texture,
567 view_embedder, platform_dispatch_table,
568 enable_impeller](flutter::Shell& shell) mutable {
569 std::unique_ptr<flutter::EmbedderSurface> embedder_surface;
570
571 if (enable_impeller) {
573 metal_dispatch_table = {
574 .present = metal_present,
575 .get_texture = metal_get_texture,
576 };
577 impeller::Flags impeller_flags;
578 impeller_flags.use_sdfs = shell.GetSettings().impeller_use_sdfs;
579 embedder_surface =
580 std::make_unique<flutter::EmbedderSurfaceMetalImpeller>(
581 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
584 metal_dispatch_table, view_embedder, impeller_flags);
585 } else {
586#if !SLIMPELLER
588 metal_dispatch_table = {
589 .present = metal_present,
590 .get_texture = metal_get_texture,
591 };
592 embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetalSkia>(
593 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
596 metal_dispatch_table, view_embedder);
597#else // !SLIMPELLER
598 FML_LOG(FATAL) << "Impeller opt-out unavailable.";
599#endif // !SLIMPELLER
600 }
601
602 return std::make_unique<flutter::PlatformViewEmbedder>(
603 shell, // delegate
604 shell.GetTaskRunners(), // task runners
605 std::move(embedder_surface), // embedder surface
606 platform_dispatch_table, // platform dispatch table
607 std::move(view_embedder) // external view embedder
608 );
609 });
610#else // SHELL_ENABLE_METAL
611 FML_LOG(ERROR) << "This Flutter Engine does not support Metal rendering.";
612 return nullptr;
613#endif // SHELL_ENABLE_METAL
614}
615
618 const FlutterRendererConfig* config,
619 void* user_data,
621 platform_dispatch_table,
622 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
623 external_view_embedder,
624 bool enable_impeller,
625 impeller::Flags impeller_flags) {
626 if (config->type != kVulkan) {
627 return nullptr;
628 }
629
630#ifdef SHELL_ENABLE_VULKAN
631 std::function<void*(VkInstance, const char*)>
632 vulkan_get_instance_proc_address =
634 VkInstance instance, const char* proc_name) -> void* {
635 return ptr(user_data, instance, proc_name);
636 };
637
638 auto vulkan_get_next_image =
639 [ptr = config->vulkan.get_next_image_callback,
640 user_data](const flutter::DlISize& frame_size) -> FlutterVulkanImage {
641 FlutterFrameInfo frame_info = {
642 .struct_size = sizeof(FlutterFrameInfo),
643 .size = {static_cast<uint32_t>(frame_size.width),
644 static_cast<uint32_t>(frame_size.height)},
645 };
646
647 return ptr(user_data, &frame_info);
648 };
649
650 auto vulkan_present_image_callback =
651 [ptr = config->vulkan.present_image_callback, user_data](
652 VkImage image, VkFormat format) -> bool {
653 FlutterVulkanImage image_desc = {
655 .image = reinterpret_cast<uint64_t>(image),
656 .format = static_cast<uint32_t>(format),
657 };
658 return ptr(user_data, &image_desc);
659 };
660
661 auto vk_instance = static_cast<VkInstance>(config->vulkan.instance);
662 auto proc_addr =
663 vulkan_get_instance_proc_address(vk_instance, "vkGetInstanceProcAddr");
664
665 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
666 std::move(external_view_embedder);
667
668#if IMPELLER_SUPPORTS_RENDERING
669 if (enable_impeller) {
671 vulkan_dispatch_table = {
673 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
674 .get_next_image = vulkan_get_next_image,
675 .present_image = vulkan_present_image_callback,
676 };
677
678 std::unique_ptr<flutter::EmbedderSurfaceVulkanImpeller> embedder_surface =
679 std::make_unique<flutter::EmbedderSurfaceVulkanImpeller>(
680 config->vulkan.version, vk_instance,
685 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
686 static_cast<VkDevice>(config->vulkan.device),
688 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
689 view_embedder, impeller_flags);
690
691 return fml::MakeCopyable(
692 [embedder_surface = std::move(embedder_surface),
693 platform_dispatch_table,
694 external_view_embedder =
695 std::move(view_embedder)](flutter::Shell& shell) mutable {
696 return std::make_unique<flutter::PlatformViewEmbedder>(
697 shell, // delegate
698 shell.GetTaskRunners(), // task runners
699 std::move(embedder_surface), // embedder surface
700 platform_dispatch_table, // platform dispatch table
701 std::move(external_view_embedder) // external view embedder
702 );
703 });
704 } else {
706 {
708 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
709 .get_next_image = vulkan_get_next_image,
710 .present_image = vulkan_present_image_callback,
711 };
712
713 std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
714 std::make_unique<flutter::EmbedderSurfaceVulkan>(
715 config->vulkan.version, vk_instance,
720 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
721 static_cast<VkDevice>(config->vulkan.device),
723 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
724 view_embedder);
725
726 return fml::MakeCopyable(
727 [embedder_surface = std::move(embedder_surface),
728 platform_dispatch_table,
729 external_view_embedder =
730 std::move(view_embedder)](flutter::Shell& shell) mutable {
731 return std::make_unique<flutter::PlatformViewEmbedder>(
732 shell, // delegate
733 shell.GetTaskRunners(), // task runners
734 std::move(embedder_surface), // embedder surface
735 platform_dispatch_table, // platform dispatch table
736 std::move(external_view_embedder) // external view embedder
737 );
738 });
739 }
740#else
743 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
744 .get_next_image = vulkan_get_next_image,
745 .present_image = vulkan_present_image_callback,
746 };
747
748 std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
749 std::make_unique<flutter::EmbedderSurfaceVulkan>(
750 config->vulkan.version, vk_instance,
755 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
756 static_cast<VkDevice>(config->vulkan.device),
758 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
759 view_embedder);
760
761 return fml::MakeCopyable(
762 [embedder_surface = std::move(embedder_surface), platform_dispatch_table,
763 external_view_embedder =
764 std::move(view_embedder)](flutter::Shell& shell) mutable {
765 return std::make_unique<flutter::PlatformViewEmbedder>(
766 shell, // delegate
767 shell.GetTaskRunners(), // task runners
768 std::move(embedder_surface), // embedder surface
769 platform_dispatch_table, // platform dispatch table
770 std::move(external_view_embedder) // external view embedder
771 );
772 });
773#endif // // IMPELLER_SUPPORTS_RENDERING
774#else // SHELL_ENABLE_VULKAN
775 FML_LOG(ERROR) << "This Flutter Engine does not support Vulkan rendering.";
776 return nullptr;
777#endif // SHELL_ENABLE_VULKAN
778}
779
782 const FlutterRendererConfig* config,
783 void* user_data,
785 platform_dispatch_table,
786 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
787 external_view_embedder) {
788 if (config->type != kSoftware) {
789 return nullptr;
790 }
791
792 auto software_present_backing_store =
794 const void* allocation, size_t row_bytes, size_t height) -> bool {
795 return ptr(user_data, allocation, row_bytes, height);
796 };
797
799 software_dispatch_table = {
800 software_present_backing_store, // required
801 };
802
803 return fml::MakeCopyable(
804 [software_dispatch_table, platform_dispatch_table,
805 external_view_embedder =
806 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
807 return std::make_unique<flutter::PlatformViewEmbedder>(
808 shell, // delegate
809 shell.GetTaskRunners(), // task runners
810 software_dispatch_table, // software dispatch table
811 platform_dispatch_table, // platform dispatch table
812 std::move(external_view_embedder) // external view embedder
813 );
814 });
815}
816
819 const FlutterRendererConfig* config,
820 void* user_data,
822 platform_dispatch_table,
823 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
824 external_view_embedder,
825 bool enable_impeller,
826 impeller::Flags impeller_flags) {
827 if (config == nullptr) {
828 return nullptr;
829 }
830
831 switch (config->type) {
832 case kOpenGL:
834 config, user_data, platform_dispatch_table,
835 std::move(external_view_embedder), enable_impeller, impeller_flags);
836 case kSoftware:
838 config, user_data, platform_dispatch_table,
839 std::move(external_view_embedder));
840 case kMetal:
842 config, user_data, platform_dispatch_table,
843 std::move(external_view_embedder), enable_impeller, impeller_flags);
844 case kVulkan:
846 config, user_data, platform_dispatch_table,
847 std::move(external_view_embedder), enable_impeller, impeller_flags);
848 default:
849 return nullptr;
850 }
851 return nullptr;
852}
853
854static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
855 GrDirectContext* context,
856 const FlutterBackingStoreConfig& config,
858#ifdef SHELL_ENABLE_GL
859 GrGLTextureInfo texture_info;
860 texture_info.fTarget = texture->target;
861 texture_info.fID = texture->name;
862 texture_info.fFormat = texture->format;
863
864 GrBackendTexture backend_texture =
865 GrBackendTextures::MakeGL(config.size.width, config.size.height,
866 skgpu::Mipmapped::kNo, texture_info);
867
868 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
869
870 std::optional<SkColorType> color_type =
871 FlutterFormatToSkColorType(texture->format);
872 if (!color_type) {
873 return nullptr;
874 }
875
876 auto surface = SkSurfaces::WrapBackendTexture(
877 context, // context
878 backend_texture, // back-end texture
879 kBottomLeft_GrSurfaceOrigin, // surface origin
880 1, // sample count
881 color_type.value(), // color type
882 SkColorSpace::MakeSRGB(), // color space
883 &surface_properties, // surface properties
884 static_cast<SkSurfaces::TextureReleaseProc>(
885 texture->destruction_callback), // release proc
886 texture->user_data // release context
887 );
888
889 if (!surface) {
890 FML_LOG(ERROR) << "Could not wrap embedder supplied render texture.";
891 return nullptr;
892 }
893
894 return surface;
895#else
896 return nullptr;
897#endif
898}
899
900static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
901 GrDirectContext* context,
902 const FlutterBackingStoreConfig& config,
904#ifdef SHELL_ENABLE_GL
905 GrGLFramebufferInfo framebuffer_info = {};
906 framebuffer_info.fFormat = framebuffer->target;
907 framebuffer_info.fFBOID = framebuffer->name;
908
909 auto backend_render_target =
910 GrBackendRenderTargets::MakeGL(config.size.width, // width
911 config.size.height, // height
912 1, // sample count
913 0, // stencil bits
914 framebuffer_info // framebuffer info
915 );
916
917 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
918
919 std::optional<SkColorType> color_type =
920 FlutterFormatToSkColorType(framebuffer->target);
921 if (!color_type) {
922 return nullptr;
923 }
924
925 auto surface = SkSurfaces::WrapBackendRenderTarget(
926 context, // context
927 backend_render_target, // backend render target
928 kBottomLeft_GrSurfaceOrigin, // surface origin
929 color_type.value(), // color type
930 SkColorSpace::MakeSRGB(), // color space
931 &surface_properties, // surface properties
932 static_cast<SkSurfaces::RenderTargetReleaseProc>(
933 framebuffer->destruction_callback), // release proc
934 framebuffer->user_data // release context
935 );
936
937 if (!surface) {
938 FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
939 return nullptr;
940 }
941 return surface;
942#else
943 return nullptr;
944#endif
945}
946
947static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
948 GrDirectContext* context,
949 const FlutterBackingStoreConfig& config,
950 const FlutterOpenGLSurface* surface) {
951#ifdef SHELL_ENABLE_GL
952 GrGLFramebufferInfo framebuffer_info = {};
953 framebuffer_info.fFormat = SAFE_ACCESS(surface, format, GL_BGRA8_EXT);
954 framebuffer_info.fFBOID = 0;
955
956 auto backend_render_target =
957 GrBackendRenderTargets::MakeGL(config.size.width, // width
958 config.size.height, // height
959 1, // sample count
960 0, // stencil bits
961 framebuffer_info // framebuffer info
962 );
963
964 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
965
966 std::optional<SkColorType> color_type =
967 FlutterFormatToSkColorType(surface->format);
968 if (!color_type) {
969 return nullptr;
970 }
971
972 auto sk_surface = SkSurfaces::WrapBackendRenderTarget(
973 context, // context
974 backend_render_target, // backend render target
975 kBottomLeft_GrSurfaceOrigin, // surface origin
976 color_type.value(), // color type
977 SkColorSpace::MakeSRGB(), // color space
978 &surface_properties, // surface properties
979 static_cast<SkSurfaces::RenderTargetReleaseProc>(
980 surface->destruction_callback), // release proc
981 surface->user_data // release context
982 );
983
984 if (!sk_surface) {
985 FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
986 return nullptr;
987 }
988 return sk_surface;
989#else
990 return nullptr;
991#endif
992}
993
994static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
995 GrDirectContext* context,
996 const FlutterBackingStoreConfig& config,
997 const FlutterSoftwareBackingStore* software) {
998 const auto image_info =
999 SkImageInfo::MakeN32Premul(config.size.width, config.size.height);
1000
1001 struct Captures {
1002 VoidCallback destruction_callback;
1003 void* user_data;
1004 };
1005 auto captures = std::make_unique<Captures>();
1006 captures->destruction_callback = software->destruction_callback;
1007 captures->user_data = software->user_data;
1008 auto release_proc = [](void* pixels, void* context) {
1009 auto captures = reinterpret_cast<Captures*>(context);
1010 if (captures->destruction_callback) {
1011 captures->destruction_callback(captures->user_data);
1012 }
1013 delete captures;
1014 };
1015
1016 auto surface =
1017 SkSurfaces::WrapPixels(image_info, // image info
1018 const_cast<void*>(software->allocation), // pixels
1019 software->row_bytes, // row bytes
1020 release_proc, // release proc
1021 captures.get() // get context
1022 );
1023
1024 if (!surface) {
1025 FML_LOG(ERROR)
1026 << "Could not wrap embedder supplied software render buffer.";
1027 if (software->destruction_callback) {
1028 software->destruction_callback(software->user_data);
1029 }
1030 return nullptr;
1031 }
1032 if (surface) {
1033 captures.release(); // Skia has assumed ownership of the struct.
1034 }
1035 return surface;
1036}
1037
1038static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
1039 GrDirectContext* context,
1040 const FlutterBackingStoreConfig& config,
1041 const FlutterSoftwareBackingStore2* software) {
1042 const auto color_info = getSkColorInfo(software->pixel_format);
1043 if (!color_info) {
1044 return nullptr;
1045 }
1046
1047 const auto image_info = SkImageInfo::Make(
1048 SkISize::Make(config.size.width, config.size.height), *color_info);
1049
1050 struct Captures {
1051 VoidCallback destruction_callback;
1052 void* user_data;
1053 };
1054 auto captures = std::make_unique<Captures>();
1055 captures->destruction_callback = software->destruction_callback;
1056 captures->user_data = software->user_data;
1057 auto release_proc = [](void* pixels, void* context) {
1058 auto captures = reinterpret_cast<Captures*>(context);
1059 if (captures->destruction_callback) {
1060 captures->destruction_callback(captures->user_data);
1061 }
1062 };
1063
1064 auto surface =
1065 SkSurfaces::WrapPixels(image_info, // image info
1066 const_cast<void*>(software->allocation), // pixels
1067 software->row_bytes, // row bytes
1068 release_proc, // release proc
1069 captures.release() // release context
1070 );
1071
1072 if (!surface) {
1073 FML_LOG(ERROR)
1074 << "Could not wrap embedder supplied software render buffer.";
1075 if (software->destruction_callback) {
1076 software->destruction_callback(software->user_data);
1077 }
1078 return nullptr;
1079 }
1080 return surface;
1081}
1082
1083static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
1084 GrDirectContext* context,
1085 const FlutterBackingStoreConfig& config,
1086 const FlutterMetalBackingStore* metal) {
1087#if defined(SHELL_ENABLE_METAL) && !SLIMPELLER
1088 GrMtlTextureInfo texture_info;
1089 if (!metal->texture.texture) {
1090 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
1091 return nullptr;
1092 }
1093 sk_cfp<FlutterMetalTextureHandle> mtl_texture;
1094 mtl_texture.retain(metal->texture.texture);
1095 texture_info.fTexture = mtl_texture;
1096 GrBackendTexture backend_texture =
1097 GrBackendTextures::MakeMtl(config.size.width, //
1098 config.size.height, //
1099 skgpu::Mipmapped::kNo, //
1100 texture_info //
1101 );
1102
1103 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
1104
1105 auto surface = SkSurfaces::WrapBackendTexture(
1106 context, // context
1107 backend_texture, // back-end texture
1108 kTopLeft_GrSurfaceOrigin, // surface origin
1109 1, // sample count
1110 kBGRA_8888_SkColorType, // color type
1111 nullptr, // color space
1112 &surface_properties, // surface properties
1113 static_cast<SkSurfaces::TextureReleaseProc>(
1114 metal->texture.destruction_callback), // release proc
1115 metal->texture.user_data // release context
1116 );
1117
1118 if (!surface) {
1119 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
1120 return nullptr;
1121 }
1122
1123 return surface;
1124#else
1125 return nullptr;
1126#endif
1127}
1128
1129#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
1130static std::optional<impeller::PixelFormat> FlutterFormatToImpellerPixelFormat(
1131 uint32_t format) {
1132 switch (format) {
1133 case GL_BGRA8_EXT:
1135 case GL_RGBA8:
1137 default:
1138 FML_LOG(ERROR) << "Cannot convert format " << format
1139 << " to impeller::PixelFormat.";
1140 return std::nullopt;
1141 }
1142}
1143
1144#endif // defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
1145
1146static std::unique_ptr<flutter::EmbedderRenderTarget>
1148 FlutterBackingStore backing_store,
1149 const fml::closure& on_release,
1150 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1151 const FlutterBackingStoreConfig& config,
1153#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
1154 auto format = FlutterFormatToImpellerPixelFormat(framebuffer->target);
1155 if (!format.has_value()) {
1156 return nullptr;
1157 }
1158
1159 const auto& gl_context =
1160 impeller::ContextGLES::Cast(*aiks_context->GetContext());
1161 const bool implicit_msaa = aiks_context->GetContext()
1162 ->GetCapabilities()
1163 ->SupportsImplicitResolvingMSAA();
1164 const auto size = impeller::ISize(config.size.width, config.size.height);
1165
1166 impeller::TextureDescriptor color0_tex;
1167 if (implicit_msaa) {
1170 } else {
1173 }
1174 color0_tex.format = format.value();
1175 color0_tex.size = size;
1176 color0_tex.usage = static_cast<impeller::TextureUsageMask>(
1179
1182 gl_context.GetReactor(), color0_tex, framebuffer->name);
1185 if (implicit_msaa) {
1187 color0.resolve_texture = color0.texture;
1188 } else {
1190 }
1191
1192 impeller::TextureDescriptor depth_stencil_texture_desc;
1193 depth_stencil_texture_desc.format = impeller::PixelFormat::kD24UnormS8Uint;
1194 depth_stencil_texture_desc.size = size;
1195 depth_stencil_texture_desc.usage = static_cast<impeller::TextureUsageMask>(
1197 if (implicit_msaa) {
1198 depth_stencil_texture_desc.type =
1200 depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount4;
1201 } else {
1202 depth_stencil_texture_desc.type = impeller::TextureType::kTexture2D;
1203 depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount1;
1204 }
1205
1206 auto depth_stencil_tex = impeller::TextureGLES::CreatePlaceholder(
1207 gl_context.GetReactor(), depth_stencil_texture_desc);
1208
1210 depth0.clear_depth = 0;
1211 depth0.texture = depth_stencil_tex;
1214
1216 stencil0.clear_stencil = 0;
1217 stencil0.texture = depth_stencil_tex;
1220
1221 impeller::RenderTarget render_target_desc;
1222
1223 render_target_desc.SetColorAttachment(color0, 0u);
1224 render_target_desc.SetDepthAttachment(depth0);
1225 render_target_desc.SetStencilAttachment(stencil0);
1226
1227 fml::closure framebuffer_destruct =
1228 [callback = framebuffer->destruction_callback,
1229 user_data = framebuffer->user_data]() { callback(user_data); };
1230
1231 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1232 backing_store, aiks_context,
1233 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1234 on_release, framebuffer_destruct);
1235#else
1236 return nullptr;
1237#endif
1238}
1239
1240static std::unique_ptr<flutter::EmbedderRenderTarget>
1242 FlutterBackingStore backing_store,
1243 const fml::closure& on_release,
1244 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1245 const FlutterBackingStoreConfig& config,
1246 const FlutterMetalBackingStore* metal) {
1247#if defined(SHELL_ENABLE_METAL) && defined(IMPELLER_SUPPORTS_RENDERING)
1248 if (!metal->texture.texture) {
1249 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
1250 return nullptr;
1251 }
1252
1253 const auto size = impeller::ISize(config.size.width, config.size.height);
1254
1255 impeller::TextureDescriptor resolve_tex_desc;
1256 resolve_tex_desc.size = size;
1259 resolve_tex_desc.usage = impeller::TextureUsage::kRenderTarget |
1261
1262 auto resolve_tex = impeller::WrapTextureMTL(
1263 resolve_tex_desc, metal->texture.texture,
1265 user_data = metal->texture.user_data]() { callback(user_data); });
1266 if (!resolve_tex) {
1267 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
1268 return nullptr;
1269 }
1270
1271 aiks_context->GetContext()->UpdateOffscreenLayerPixelFormat(
1272 resolve_tex->GetTextureDescriptor().format);
1273
1274 resolve_tex->SetLabel("ImpellerBackingStoreResolve");
1275
1276 impeller::TextureDescriptor msaa_tex_desc;
1280 msaa_tex_desc.format = resolve_tex->GetTextureDescriptor().format;
1281 msaa_tex_desc.size = size;
1283
1284 auto msaa_tex =
1285 aiks_context->GetContext()->GetResourceAllocator()->CreateTexture(
1286 msaa_tex_desc);
1287 if (!msaa_tex) {
1288 FML_LOG(ERROR) << "Could not allocate MSAA color texture.";
1289 return nullptr;
1290 }
1291 msaa_tex->SetLabel("ImpellerBackingStoreColorMSAA");
1292
1294 color0.texture = msaa_tex;
1298 color0.resolve_texture = resolve_tex;
1299
1300 impeller::RenderTarget render_target_desc;
1301 render_target_desc.SetColorAttachment(color0, 0u);
1302
1303 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1304 backing_store, aiks_context,
1305 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1306 on_release, fml::closure());
1307#else
1308 return nullptr;
1309#endif
1310}
1311
1312static sk_sp<SkSurface> MakeSkSurfaceFromBackingStore(
1313 GrDirectContext* context,
1314 const FlutterBackingStoreConfig& config,
1316#ifdef SHELL_ENABLE_VULKAN
1317 if (!vulkan->image) {
1318 FML_LOG(ERROR) << "Embedder supplied null Vulkan image.";
1319 return nullptr;
1320 }
1321 GrVkImageInfo image_info = {
1322 .fImage = reinterpret_cast<VkImage>(vulkan->image->image),
1323 .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
1324 .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1325 .fFormat = static_cast<VkFormat>(vulkan->image->format),
1326 .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1327 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1328 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1329 VK_IMAGE_USAGE_SAMPLED_BIT,
1330 .fSampleCount = 1,
1331 .fLevelCount = 1,
1332 };
1333 auto backend_texture = GrBackendTextures::MakeVk(
1334 config.size.width, config.size.height, image_info);
1335
1336 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
1337
1338 auto surface = SkSurfaces::WrapBackendTexture(
1339 context, // context
1340 backend_texture, // back-end texture
1341 kTopLeft_GrSurfaceOrigin, // surface origin
1342 1, // sample count
1344 static_cast<VkFormat>(vulkan->image->format)), // color type
1345 SkColorSpace::MakeSRGB(), // color space
1346 &surface_properties, // surface properties
1347 static_cast<SkSurfaces::TextureReleaseProc>(
1348 vulkan->destruction_callback), // release proc
1349 vulkan->user_data // release context
1350 );
1351
1352 if (!surface) {
1353 FML_LOG(ERROR) << "Could not wrap embedder supplied Vulkan render texture.";
1354 return nullptr;
1355 }
1356
1357 return surface;
1358#else
1359 return nullptr;
1360#endif
1361}
1362
1363static std::unique_ptr<flutter::EmbedderRenderTarget>
1365 FlutterBackingStore backing_store,
1366 sk_sp<SkSurface> skia_surface,
1367 fml::closure on_release,
1370 on_clear_current) {
1371 if (!skia_surface) {
1372 return nullptr;
1373 }
1374 return std::make_unique<flutter::EmbedderRenderTargetSkia>(
1375 backing_store, std::move(skia_surface), std::move(on_release),
1376 std::move(on_make_current), std::move(on_clear_current));
1377}
1378
1379static std::unique_ptr<flutter::EmbedderRenderTarget>
1381 sk_sp<SkSurface> skia_surface,
1382 fml::closure on_release) {
1383 return MakeRenderTargetFromSkSurface(backing_store, std::move(skia_surface),
1384 std::move(on_release), nullptr, nullptr);
1385}
1386
1387static std::unique_ptr<flutter::EmbedderRenderTarget>
1389 const FlutterCompositor* compositor,
1390 const FlutterBackingStoreConfig& config,
1391 GrDirectContext* context,
1392 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1393 bool enable_impeller) {
1394 FlutterBackingStore backing_store = {};
1395 backing_store.struct_size = sizeof(backing_store);
1396
1397 // Safe access checks on the compositor struct have been performed in
1398 // InferExternalViewEmbedderFromArgs and are not necessary here.
1399 auto c_create_callback = compositor->create_backing_store_callback;
1400 auto c_collect_callback = compositor->collect_backing_store_callback;
1401
1402 {
1403 TRACE_EVENT0("flutter", "FlutterCompositorCreateBackingStore");
1404 if (!c_create_callback(&config, &backing_store, compositor->user_data)) {
1405 FML_LOG(ERROR) << "Could not create the embedder backing store.";
1406 return nullptr;
1407 }
1408 }
1409
1410 if (backing_store.struct_size != sizeof(backing_store)) {
1411 FML_LOG(ERROR) << "Embedder modified the backing store struct size.";
1412 return nullptr;
1413 }
1414
1415 // In case we return early without creating an embedder render target, the
1416 // embedder has still given us ownership of its baton which we must return
1417 // back to it. If this method is successful, the closure is released when the
1418 // render target is eventually released.
1419 fml::ScopedCleanupClosure collect_callback(
1420 [c_collect_callback, backing_store, user_data = compositor->user_data]() {
1421 TRACE_EVENT0("flutter", "FlutterCompositorCollectBackingStore");
1422 c_collect_callback(&backing_store, user_data);
1423 });
1424
1425 // No safe access checks on the renderer are necessary since we allocated
1426 // the struct.
1427
1428 std::unique_ptr<flutter::EmbedderRenderTarget> render_target;
1429
1430 switch (backing_store.type) {
1432 switch (backing_store.open_gl.type) {
1434 auto skia_surface = MakeSkSurfaceFromBackingStore(
1435 context, config, &backing_store.open_gl.texture);
1436 render_target = MakeRenderTargetFromSkSurface(
1437 backing_store, std::move(skia_surface),
1438 collect_callback.Release());
1439 break;
1440 }
1442 if (enable_impeller) {
1444 backing_store, collect_callback.Release(), aiks_context, config,
1445 &backing_store.open_gl.framebuffer);
1446 break;
1447 } else {
1448 auto skia_surface = MakeSkSurfaceFromBackingStore(
1449 context, config, &backing_store.open_gl.framebuffer);
1450 render_target = MakeRenderTargetFromSkSurface(
1451 backing_store, std::move(skia_surface),
1452 collect_callback.Release());
1453 break;
1454 }
1455 }
1456
1458 auto on_make_current =
1460 context = backing_store.open_gl.surface.user_data]()
1462 bool invalidate_api_state = false;
1463 bool ok = callback(context, &invalidate_api_state);
1464 return {ok, invalidate_api_state};
1465 };
1466
1467 auto on_clear_current =
1469 context = backing_store.open_gl.surface.user_data]()
1471 bool invalidate_api_state = false;
1472 bool ok = callback(context, &invalidate_api_state);
1473 return {ok, invalidate_api_state};
1474 };
1475
1476 if (enable_impeller) {
1477 // TODO(https://github.com/flutter/flutter/issues/151670): Implement
1478 // GL Surface backing stores for Impeller.
1479 FML_LOG(ERROR) << "Unimplemented";
1480 break;
1481 } else {
1482 auto skia_surface = MakeSkSurfaceFromBackingStore(
1483 context, config, &backing_store.open_gl.surface);
1484
1485 render_target = MakeRenderTargetFromSkSurface(
1486 backing_store, std::move(skia_surface),
1487 collect_callback.Release(), on_make_current, on_clear_current);
1488 break;
1489 }
1490 }
1491 }
1492 break;
1493 }
1494
1496 auto skia_surface = MakeSkSurfaceFromBackingStore(
1497 context, config, &backing_store.software);
1498 render_target = MakeRenderTargetFromSkSurface(
1499 backing_store, std::move(skia_surface), collect_callback.Release());
1500 break;
1501 }
1503 auto skia_surface = MakeSkSurfaceFromBackingStore(
1504 context, config, &backing_store.software2);
1505 render_target = MakeRenderTargetFromSkSurface(
1506 backing_store, std::move(skia_surface), collect_callback.Release());
1507 break;
1508 }
1510 if (enable_impeller) {
1512 backing_store, collect_callback.Release(), aiks_context, config,
1513 &backing_store.metal);
1514 } else {
1515 auto skia_surface = MakeSkSurfaceFromBackingStore(context, config,
1516 &backing_store.metal);
1517 render_target = MakeRenderTargetFromSkSurface(
1518 backing_store, std::move(skia_surface), collect_callback.Release());
1519 }
1520 break;
1521 }
1523 if (enable_impeller) {
1524 FML_LOG(ERROR) << "Unimplemented";
1525 break;
1526 } else {
1527 auto skia_surface = MakeSkSurfaceFromBackingStore(
1528 context, config, &backing_store.vulkan);
1529 render_target = MakeRenderTargetFromSkSurface(
1530 backing_store, std::move(skia_surface), collect_callback.Release());
1531 break;
1532 }
1533 }
1534 };
1535
1536 if (!render_target) {
1537 FML_LOG(ERROR) << "Could not create a surface from an embedder provided "
1538 "render target.";
1539 }
1540 return render_target;
1541}
1542
1543/// Creates an EmbedderExternalViewEmbedder.
1544///
1545/// When a non-OK status is returned, engine startup should be halted.
1548 bool enable_impeller) {
1549 if (compositor == nullptr) {
1550 return std::unique_ptr<flutter::EmbedderExternalViewEmbedder>{nullptr};
1551 }
1552
1553 auto c_create_callback =
1554 SAFE_ACCESS(compositor, create_backing_store_callback, nullptr);
1555 auto c_collect_callback =
1556 SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr);
1557 auto c_present_callback =
1558 SAFE_ACCESS(compositor, present_layers_callback, nullptr);
1559 auto c_present_view_callback =
1560 SAFE_ACCESS(compositor, present_view_callback, nullptr);
1561 bool avoid_backing_store_cache =
1562 SAFE_ACCESS(compositor, avoid_backing_store_cache, false);
1563
1564 // Make sure the required callbacks are present
1565 if (!c_create_callback || !c_collect_callback) {
1567 "Required compositor callbacks absent.");
1568 }
1569 // Either the present view or the present layers callback must be provided.
1570 if ((!c_present_view_callback && !c_present_callback) ||
1571 (c_present_view_callback && c_present_callback)) {
1573 "Either present_layers_callback or "
1574 "present_view_callback must be provided but not both.");
1575 }
1576
1577 FlutterCompositor captured_compositor = *compositor;
1578
1580 create_render_target_callback =
1581 [captured_compositor, enable_impeller](
1582 GrDirectContext* context,
1583 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1584 const auto& config) {
1585 return CreateEmbedderRenderTarget(&captured_compositor, config,
1586 context, aiks_context,
1587 enable_impeller);
1588 };
1589
1591 if (c_present_callback) {
1592 present_callback = [c_present_callback, user_data = compositor->user_data](
1593 FlutterViewId view_id, const auto& layers) {
1594 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1595 return c_present_callback(const_cast<const FlutterLayer**>(layers.data()),
1596 layers.size(), user_data);
1597 };
1598 } else {
1599 FML_DCHECK(c_present_view_callback != nullptr);
1600 present_callback = [c_present_view_callback,
1601 user_data = compositor->user_data](
1602 FlutterViewId view_id, const auto& layers) {
1603 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1604
1605 FlutterPresentViewInfo info = {
1607 .view_id = view_id,
1608 .layers = const_cast<const FlutterLayer**>(layers.data()),
1610 .user_data = user_data,
1611 };
1612
1613 return c_present_view_callback(&info);
1614 };
1615 }
1616
1617 return std::make_unique<flutter::EmbedderExternalViewEmbedder>(
1618 avoid_backing_store_cache, create_render_target_callback,
1619 present_callback);
1620}
1621
1622// Translates embedder metrics to engine metrics, or returns a string on error.
1623static std::variant<flutter::ViewportMetrics, std::string>
1625 const FlutterWindowMetricsEvent* flutter_metrics) {
1626 if (flutter_metrics == nullptr) {
1627 return "Invalid metrics handle.";
1628 }
1629
1631
1632 metrics.physical_width = SAFE_ACCESS(flutter_metrics, width, 0.0);
1633 metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
1634
1635 if (SAFE_ACCESS(flutter_metrics, has_constraints, false)) {
1637 flutter_metrics, min_width_constraint, metrics.physical_width);
1639 flutter_metrics, max_width_constraint, metrics.physical_width);
1641 flutter_metrics, min_height_constraint, metrics.physical_height);
1643 flutter_metrics, max_height_constraint, metrics.physical_height);
1644 } else {
1649 }
1650
1651 if (metrics.physical_width < metrics.physical_min_width_constraint ||
1655 return "Window metrics are invalid. Width and height must be within the "
1656 "specified constraints.";
1657 }
1658
1659 metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
1660 metrics.physical_view_inset_top =
1661 SAFE_ACCESS(flutter_metrics, physical_view_inset_top, 0.0);
1663 SAFE_ACCESS(flutter_metrics, physical_view_inset_right, 0.0);
1665 SAFE_ACCESS(flutter_metrics, physical_view_inset_bottom, 0.0);
1666 metrics.physical_view_inset_left =
1667 SAFE_ACCESS(flutter_metrics, physical_view_inset_left, 0.0);
1668 metrics.display_id = SAFE_ACCESS(flutter_metrics, display_id, 0);
1669
1670 if (metrics.device_pixel_ratio <= 0.0) {
1671 return "Device pixel ratio was invalid. It must be greater than zero.";
1672 }
1673
1674 if (metrics.physical_view_inset_top < 0 ||
1675 metrics.physical_view_inset_right < 0 ||
1676 metrics.physical_view_inset_bottom < 0 ||
1677 metrics.physical_view_inset_left < 0) {
1678 return "Physical view insets are invalid. They must be non-negative.";
1679 }
1680
1681 if (metrics.physical_view_inset_top > metrics.physical_height ||
1682 metrics.physical_view_inset_right > metrics.physical_width ||
1683 metrics.physical_view_inset_bottom > metrics.physical_height ||
1684 metrics.physical_view_inset_left > metrics.physical_width) {
1685 return "Physical view insets are invalid. They cannot be greater than "
1686 "physical height or width.";
1687 }
1688
1689 return metrics;
1690}
1691
1693 std::unique_ptr<flutter::PlatformMessage> message;
1694};
1695
1696struct LoadedElfDeleter {
1697 void operator()(Dart_LoadedElf* elf) {
1698 if (elf) {
1699 ::Dart_UnloadELF(elf);
1700 }
1701 }
1702};
1703
1704using UniqueLoadedElf = std::unique_ptr<Dart_LoadedElf, LoadedElfDeleter>;
1705
1706struct _FlutterEngineAOTData {
1707 UniqueLoadedElf loaded_elf = nullptr;
1708 const uint8_t* vm_snapshot_data = nullptr;
1709 const uint8_t* vm_snapshot_instrs = nullptr;
1710 const uint8_t* vm_isolate_data = nullptr;
1711 const uint8_t* vm_isolate_instrs = nullptr;
1712};
1713
1715 const FlutterEngineAOTDataSource* source,
1716 FlutterEngineAOTData* data_out) {
1719 "AOT data can only be created in AOT mode.");
1720 } else if (!source) {
1721 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null source specified.");
1722 } else if (!data_out) {
1723 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null data_out specified.");
1724 }
1725
1726 switch (source->type) {
1728 if (!source->elf_path || !fml::IsFile(source->elf_path)) {
1730 "Invalid ELF path specified.");
1731 }
1732
1733 auto aot_data = std::make_unique<_FlutterEngineAOTData>();
1734 const char* error = nullptr;
1735
1736#if OS_FUCHSIA
1737 // TODO(gw280): https://github.com/flutter/flutter/issues/50285
1738 // Dart doesn't implement Dart_LoadELF on Fuchsia
1739 Dart_LoadedElf* loaded_elf = nullptr;
1740#else
1741 Dart_LoadedElf* loaded_elf =
1742 Dart_LoadELF(source->elf_path, // file path
1743 0, // file offset
1744 &error, // error (out)
1745 &aot_data->vm_isolate_data, // vm isolate data (out)
1746 &aot_data->vm_isolate_instrs // vm isolate instr (out)
1747 );
1748 if (loaded_elf != nullptr) {
1749 aot_data->vm_snapshot_data = aot_data->vm_isolate_data;
1750 aot_data->vm_snapshot_instrs = aot_data->vm_isolate_instrs;
1751 }
1752#endif
1753
1754 if (loaded_elf == nullptr) {
1756 }
1757
1758 aot_data->loaded_elf.reset(loaded_elf);
1759
1760 *data_out = aot_data.release();
1761 return kSuccess;
1762 }
1763 }
1764
1765 return LOG_EMBEDDER_ERROR(
1767 "Invalid FlutterEngineAOTDataSourceType type specified.");
1768}
1769
1771 if (!data) {
1772 // Deleting a null object should be a no-op.
1773 return kSuccess;
1774 }
1775
1776 // Created in a unique pointer in `FlutterEngineCreateAOTData`.
1777 delete data;
1778 return kSuccess;
1779}
1780
1781// Constructs appropriate mapping callbacks if JIT snapshot locations have been
1782// explictly specified.
1784 flutter::Settings& settings) {
1785 auto make_mapping_callback = [](const char* path, bool executable) {
1786 return [path, executable]() {
1787 if (executable) {
1789 } else {
1791 }
1792 };
1793 };
1794
1795 // Users are allowed to specify only certain snapshots if they so desire.
1796 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1797 settings.vm_snapshot_data = make_mapping_callback(
1798 reinterpret_cast<const char*>(args->vm_snapshot_data), false);
1799 }
1800
1801 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1802 settings.vm_snapshot_instr = make_mapping_callback(
1803 reinterpret_cast<const char*>(args->vm_snapshot_instructions), true);
1804 }
1805
1806 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1807 settings.isolate_snapshot_data = make_mapping_callback(
1808 reinterpret_cast<const char*>(args->isolate_snapshot_data), false);
1809 }
1810
1811 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1812 settings.isolate_snapshot_instr = make_mapping_callback(
1813 reinterpret_cast<const char*>(args->isolate_snapshot_instructions),
1814 true);
1815 }
1816
1817#if !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
1818 settings.dart_library_sources_kernel = []() {
1819 return std::make_unique<fml::NonOwnedMapping>(kPlatformStrongDill,
1821 };
1822#endif // !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE ==
1823 // FLUTTER_RUNTIME_MODE_DEBUG)
1824}
1825
1827 const FlutterProjectArgs* args,
1828 flutter::Settings& settings) { // NOLINT(google-runtime-references)
1829 // There are no ownership concerns here as all mappings are owned by the
1830 // embedder and not the engine.
1831 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
1832 return [mapping, size]() {
1833 return std::make_unique<fml::NonOwnedMapping>(mapping, size);
1834 };
1835 };
1836
1837 if (SAFE_ACCESS(args, aot_data, nullptr) != nullptr) {
1838 settings.vm_snapshot_data =
1839 make_mapping_callback(args->aot_data->vm_snapshot_data, 0);
1840
1841 settings.vm_snapshot_instr =
1842 make_mapping_callback(args->aot_data->vm_snapshot_instrs, 0);
1843
1844 settings.isolate_snapshot_data =
1845 make_mapping_callback(args->aot_data->vm_isolate_data, 0);
1846
1847 settings.isolate_snapshot_instr =
1848 make_mapping_callback(args->aot_data->vm_isolate_instrs, 0);
1849 }
1850
1851 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1852 settings.vm_snapshot_data = make_mapping_callback(
1853 args->vm_snapshot_data, SAFE_ACCESS(args, vm_snapshot_data_size, 0));
1854 }
1855
1856 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1857 settings.vm_snapshot_instr = make_mapping_callback(
1858 args->vm_snapshot_instructions,
1859 SAFE_ACCESS(args, vm_snapshot_instructions_size, 0));
1860 }
1861
1862 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1863 settings.isolate_snapshot_data =
1864 make_mapping_callback(args->isolate_snapshot_data,
1865 SAFE_ACCESS(args, isolate_snapshot_data_size, 0));
1866 }
1867
1868 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1869 settings.isolate_snapshot_instr = make_mapping_callback(
1870 args->isolate_snapshot_instructions,
1871 SAFE_ACCESS(args, isolate_snapshot_instructions_size, 0));
1872 }
1873}
1874
1875// Create a callback to notify the embedder of semantic updates
1876// using the legacy embedder callbacks 'update_semantics_node_callback' and
1877// 'update_semantics_custom_action_callback'.
1880 FlutterUpdateSemanticsNodeCallback update_semantics_node_callback,
1882 update_semantics_custom_action_callback,
1883 void* user_data) {
1884 return [update_semantics_node_callback,
1885 update_semantics_custom_action_callback, user_data](
1886 int64_t view_id, const flutter::SemanticsNodeUpdates& nodes,
1888 flutter::EmbedderSemanticsUpdate update{nodes, actions};
1889 FlutterSemanticsUpdate* update_ptr = update.get();
1890
1891 // First, queue all node and custom action updates.
1892 if (update_semantics_node_callback != nullptr) {
1893 for (size_t i = 0; i < update_ptr->nodes_count; i++) {
1894 update_semantics_node_callback(&update_ptr->nodes[i], user_data);
1895 }
1896 }
1897
1898 if (update_semantics_custom_action_callback != nullptr) {
1899 for (size_t i = 0; i < update_ptr->custom_actions_count; i++) {
1900 update_semantics_custom_action_callback(&update_ptr->custom_actions[i],
1901 user_data);
1902 }
1903 }
1904
1905 // Second, mark node and action batches completed now that all
1906 // updates are queued.
1907 if (update_semantics_node_callback != nullptr) {
1908 const FlutterSemanticsNode batch_end_sentinel = {
1909 sizeof(FlutterSemanticsNode),
1911 };
1912 update_semantics_node_callback(&batch_end_sentinel, user_data);
1913 }
1914
1915 if (update_semantics_custom_action_callback != nullptr) {
1916 const FlutterSemanticsCustomAction batch_end_sentinel = {
1919 };
1920 update_semantics_custom_action_callback(&batch_end_sentinel, user_data);
1921 }
1922 };
1923}
1924
1925// Create a callback to notify the embedder of semantic updates
1926// using the deprecated embedder callback 'update_semantics_callback'.
1929 FlutterUpdateSemanticsCallback update_semantics_callback,
1930 void* user_data) {
1931 return [update_semantics_callback, user_data](
1932 int64_t view_id, const flutter::SemanticsNodeUpdates& nodes,
1934 flutter::EmbedderSemanticsUpdate update{nodes, actions};
1935
1936 update_semantics_callback(update.get(), user_data);
1937 };
1938}
1939
1940// Create a callback to notify the embedder of semantic updates
1941// using the new embedder callback 'update_semantics_callback2'.
1944 FlutterUpdateSemanticsCallback2 update_semantics_callback,
1945 void* user_data) {
1946 return [update_semantics_callback, user_data](
1947 int64_t view_id, const flutter::SemanticsNodeUpdates& nodes,
1949 flutter::EmbedderSemanticsUpdate2 update{view_id, nodes, actions};
1950
1951 update_semantics_callback(update.get(), user_data);
1952 };
1953}
1954
1955// Creates a callback that receives semantic updates from the engine
1956// and notifies the embedder's callback(s). Returns null if the embedder
1957// did not register any callbacks.
1960 void* user_data) {
1961 // There are three variants for the embedder API's semantic update callbacks.
1962 // Create a callback that maps to the embedder's desired semantic update API.
1963 //
1964 // Handle the case where the embedder registered the callback
1965 // 'updated_semantics_callback2'
1966 if (SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr) {
1968 args->update_semantics_callback2, user_data);
1969 }
1970
1971 // Handle the case where the embedder registered the deprecated callback
1972 // 'update_semantics_callback'.
1973 if (SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr) {
1975 args->update_semantics_callback, user_data);
1976 }
1977
1978 // Handle the case where the embedder registered the deprecated callbacks
1979 // 'update_semantics_node_callback' and
1980 // 'update_semantics_custom_action_callback'.
1981 FlutterUpdateSemanticsNodeCallback update_semantics_node_callback = nullptr;
1982 if (SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr) {
1983 update_semantics_node_callback = args->update_semantics_node_callback;
1984 }
1985
1987 update_semantics_custom_action_callback = nullptr;
1988 if (SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
1989 nullptr) {
1990 update_semantics_custom_action_callback =
1991 args->update_semantics_custom_action_callback;
1992 }
1993
1994 if (update_semantics_node_callback != nullptr ||
1995 update_semantics_custom_action_callback != nullptr) {
1997 update_semantics_node_callback, update_semantics_custom_action_callback,
1998 user_data);
1999 }
2000
2001 // Handle the case where the embedder registered no callbacks.
2002 return nullptr;
2003}
2004
2006 const FlutterRendererConfig* config,
2007 const FlutterProjectArgs* args,
2008 void* user_data,
2010 engine_out) {
2011 auto result =
2012 FlutterEngineInitialize(version, config, args, user_data, engine_out);
2013
2014 if (result != kSuccess) {
2015 return result;
2016 }
2017
2018 return FlutterEngineRunInitialized(*engine_out);
2019}
2020
2022 const FlutterRendererConfig* config,
2023 const FlutterProjectArgs* args,
2024 void* user_data,
2026 engine_out) {
2027 // Step 0: Figure out arguments for shell creation.
2028 if (version != FLUTTER_ENGINE_VERSION) {
2029 return LOG_EMBEDDER_ERROR(
2031 "Flutter embedder version mismatch. There has been a breaking change. "
2032 "Please consult the changelog and update the embedder.");
2033 }
2034
2035 if (engine_out == nullptr) {
2037 "The engine out parameter was missing.");
2038 }
2039
2040 if (args == nullptr) {
2042 "The Flutter project arguments were missing.");
2043 }
2044
2045 if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr) {
2046 return LOG_EMBEDDER_ERROR(
2048 "The assets path in the Flutter project arguments was missing.");
2049 }
2050
2051 if (SAFE_ACCESS(args, main_path__unused__, nullptr) != nullptr) {
2052 FML_LOG(WARNING)
2053 << "FlutterProjectArgs.main_path is deprecated and should be set null.";
2054 }
2055
2056 if (SAFE_ACCESS(args, packages_path__unused__, nullptr) != nullptr) {
2057 FML_LOG(WARNING) << "FlutterProjectArgs.packages_path is deprecated and "
2058 "should be set null.";
2059 }
2060
2061 if (!IsRendererValid(config)) {
2063 "The renderer configuration was invalid.");
2064 }
2065
2066 std::string icu_data_path;
2067 if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) {
2068 icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr);
2069 }
2070
2071#if !SLIMPELLER
2072 if (SAFE_ACCESS(args, persistent_cache_path, nullptr) != nullptr) {
2073 std::string persistent_cache_path =
2074 SAFE_ACCESS(args, persistent_cache_path, nullptr);
2076 }
2077
2078 if (SAFE_ACCESS(args, is_persistent_cache_read_only, false)) {
2080 }
2081#endif // !SLIMPELLER
2082
2083 fml::CommandLine command_line;
2084 if (SAFE_ACCESS(args, command_line_argc, 0) != 0 &&
2085 SAFE_ACCESS(args, command_line_argv, nullptr) != nullptr) {
2086 command_line = fml::CommandLineFromArgcArgv(
2087 SAFE_ACCESS(args, command_line_argc, 0),
2088 SAFE_ACCESS(args, command_line_argv, nullptr));
2089 }
2090
2091 flutter::Settings settings = flutter::SettingsFromCommandLine(command_line);
2092
2093 if (SAFE_ACCESS(args, aot_data, nullptr)) {
2094 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) ||
2095 SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) ||
2096 SAFE_ACCESS(args, isolate_snapshot_data, nullptr) ||
2097 SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr)) {
2098 return LOG_EMBEDDER_ERROR(
2100 "Multiple AOT sources specified. Embedders should provide either "
2101 "*_snapshot_* buffers or aot_data, not both.");
2102 }
2103 }
2104
2107 } else {
2109 }
2110
2111 settings.icu_data_path = icu_data_path;
2112 settings.assets_path = args->assets_path;
2113 settings.leak_vm = !SAFE_ACCESS(args, shutdown_dart_vm_when_done, false);
2114 settings.old_gen_heap_size = SAFE_ACCESS(args, dart_old_gen_heap_size, -1);
2115 settings.enable_wide_gamut = SAFE_ACCESS(args, enable_wide_gamut, false);
2116
2118 // Verify the assets path contains Dart 2 kernel assets.
2119 const std::string kApplicationKernelSnapshotFileName = "kernel_blob.bin";
2120 std::string application_kernel_path = fml::paths::JoinPaths(
2122 if (!fml::IsFile(application_kernel_path)) {
2123 return LOG_EMBEDDER_ERROR(
2125 "Not running in AOT mode but could not resolve the kernel binary.");
2126 }
2128 }
2129
2130 if (SAFE_ACCESS(args, root_isolate_create_callback, nullptr) != nullptr) {
2132 SAFE_ACCESS(args, root_isolate_create_callback, nullptr);
2134 [callback, user_data](const auto& isolate) { callback(user_data); };
2135 }
2136
2137 // Wire up callback for engine and print logging.
2138 if (SAFE_ACCESS(args, log_message_callback, nullptr) != nullptr) {
2140 SAFE_ACCESS(args, log_message_callback, nullptr);
2142 const std::string& tag,
2143 const std::string& message) {
2144 callback(tag.c_str(), message.c_str(), user_data);
2145 };
2146 } else {
2147 settings.log_message_callback = [](const std::string& tag,
2148 const std::string& message) {
2149 // Fall back to logging to stdout if unspecified.
2150 if (tag.empty()) {
2151 std::cout << tag << ": ";
2152 }
2153 std::cout << message << std::endl;
2154 };
2155 }
2156
2157 if (SAFE_ACCESS(args, log_tag, nullptr) != nullptr) {
2158 settings.log_tag = SAFE_ACCESS(args, log_tag, nullptr);
2159 }
2160
2161 bool has_update_semantics_2_callback =
2162 SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr;
2163 bool has_update_semantics_callback =
2164 SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr;
2165 bool has_legacy_update_semantics_callback =
2166 SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr ||
2167 SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
2168 nullptr;
2169
2170 int semantic_callback_count = (has_update_semantics_2_callback ? 1 : 0) +
2171 (has_update_semantics_callback ? 1 : 0) +
2172 (has_legacy_update_semantics_callback ? 1 : 0);
2173
2174 if (semantic_callback_count > 1) {
2175 return LOG_EMBEDDER_ERROR(
2177 "Multiple semantics update callbacks provided. "
2178 "Embedders should provide either `update_semantics_callback2`, "
2179 "`update_semantics_callback`, or both "
2180 "`update_semantics_node_callback` and "
2181 "`update_semantics_custom_action_callback`.");
2182 }
2183
2185 update_semantics_callback =
2187
2189 platform_message_response_callback = nullptr;
2190 if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) {
2191 platform_message_response_callback =
2192 [ptr = args->platform_message_callback,
2193 user_data](std::unique_ptr<flutter::PlatformMessage> message) {
2194 auto handle = new FlutterPlatformMessageResponseHandle();
2195 const FlutterPlatformMessage incoming_message = {
2196 sizeof(FlutterPlatformMessage), // struct_size
2197 message->channel().c_str(), // channel
2198 message->data().GetMapping(), // message
2199 message->data().GetSize(), // message_size
2200 handle, // response_handle
2201 };
2202 handle->message = std::move(message);
2203 return ptr(&incoming_message, user_data);
2204 };
2205 }
2206
2207 flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr;
2208 if (SAFE_ACCESS(args, vsync_callback, nullptr) != nullptr) {
2209 vsync_callback = [ptr = args->vsync_callback, user_data](intptr_t baton) {
2210 return ptr(user_data, baton);
2211 };
2212 }
2213
2215 compute_platform_resolved_locale_callback = nullptr;
2216 if (SAFE_ACCESS(args, compute_platform_resolved_locale_callback, nullptr) !=
2217 nullptr) {
2218 compute_platform_resolved_locale_callback =
2219 [ptr = args->compute_platform_resolved_locale_callback](
2220 const std::vector<std::string>& supported_locales_data) {
2221 const size_t number_of_strings_per_locale = 3;
2222 size_t locale_count =
2223 supported_locales_data.size() / number_of_strings_per_locale;
2224 std::vector<FlutterLocale> supported_locales;
2225 std::vector<const FlutterLocale*> supported_locales_ptr;
2226 for (size_t i = 0; i < locale_count; ++i) {
2227 supported_locales.push_back(
2228 {.struct_size = sizeof(FlutterLocale),
2229 .language_code =
2230 supported_locales_data[i * number_of_strings_per_locale +
2231 0]
2232 .c_str(),
2233 .country_code =
2234 supported_locales_data[i * number_of_strings_per_locale +
2235 1]
2236 .c_str(),
2237 .script_code =
2238 supported_locales_data[i * number_of_strings_per_locale +
2239 2]
2240 .c_str(),
2241 .variant_code = nullptr});
2242 supported_locales_ptr.push_back(&supported_locales[i]);
2243 }
2244
2245 const FlutterLocale* result =
2246 ptr(supported_locales_ptr.data(), locale_count);
2247
2248 std::unique_ptr<std::vector<std::string>> out =
2249 std::make_unique<std::vector<std::string>>();
2250 if (result) {
2251 std::string language_code(SAFE_ACCESS(result, language_code, ""));
2252 if (language_code != "") {
2253 out->push_back(language_code);
2254 out->emplace_back(SAFE_ACCESS(result, country_code, ""));
2255 out->emplace_back(SAFE_ACCESS(result, script_code, ""));
2256 }
2257 }
2258 return out;
2259 };
2260 }
2261
2263 on_pre_engine_restart_callback = nullptr;
2264 if (SAFE_ACCESS(args, on_pre_engine_restart_callback, nullptr) != nullptr) {
2265 on_pre_engine_restart_callback = [ptr =
2266 args->on_pre_engine_restart_callback,
2267 user_data]() { return ptr(user_data); };
2268 }
2269
2271 nullptr;
2272 if (SAFE_ACCESS(args, channel_update_callback, nullptr) != nullptr) {
2273 channel_update_callback = [ptr = args->channel_update_callback, user_data](
2274 const std::string& name, bool listening) {
2275 FlutterChannelUpdate update{sizeof(FlutterChannelUpdate), name.c_str(),
2276 listening};
2277 ptr(&update, user_data);
2278 };
2279 }
2280
2282 view_focus_change_request_callback = nullptr;
2283 if (SAFE_ACCESS(args, view_focus_change_request_callback, nullptr) !=
2284 nullptr) {
2285 view_focus_change_request_callback =
2286 [ptr = args->view_focus_change_request_callback,
2288 FlutterViewFocusChangeRequest embedder_request{
2290 .view_id = request.view_id(),
2291 .state = static_cast<FlutterViewFocusState>(request.state()),
2292 .direction =
2293 static_cast<FlutterViewFocusDirection>(request.direction()),
2294 };
2295 ptr(&embedder_request, user_data);
2296 };
2297 }
2298
2299 auto external_view_embedder_result = InferExternalViewEmbedderFromArgs(
2300 SAFE_ACCESS(args, compositor, nullptr), settings.enable_impeller);
2301 if (!external_view_embedder_result.ok()) {
2302 FML_LOG(ERROR) << external_view_embedder_result.status().message();
2304 "Compositor arguments were invalid.");
2305 }
2306
2308 {
2309 update_semantics_callback, //
2310 platform_message_response_callback, //
2311 vsync_callback, //
2312 compute_platform_resolved_locale_callback, //
2313 on_pre_engine_restart_callback, //
2314 channel_update_callback, //
2315 view_focus_change_request_callback, //
2316 };
2317
2318 impeller::Flags impeller_flags;
2319 impeller_flags.use_sdfs = settings.impeller_use_sdfs;
2320 impeller_flags.antialiased_lines = settings.impeller_antialiased_lines;
2321
2322 auto on_create_platform_view = InferPlatformViewCreationCallback(
2323 config, user_data, platform_dispatch_table,
2324 std::move(external_view_embedder_result.value()),
2325 settings.enable_impeller, impeller_flags);
2326
2327 if (!on_create_platform_view) {
2328 return LOG_EMBEDDER_ERROR(
2330 "Could not infer platform view creation callback.");
2331 }
2332
2334 [](flutter::Shell& shell) {
2335 return std::make_unique<flutter::Rasterizer>(shell);
2336 };
2337
2338 using ExternalTextureResolver = flutter::EmbedderExternalTextureResolver;
2339 std::unique_ptr<ExternalTextureResolver> external_texture_resolver;
2340 external_texture_resolver = std::make_unique<ExternalTextureResolver>();
2341
2342#ifdef SHELL_ENABLE_GL
2344 external_texture_callback;
2345 if (config->type == kOpenGL) {
2346 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
2347 if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
2348 nullptr) != nullptr) {
2349 external_texture_callback =
2350 [ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
2351 int64_t texture_identifier, size_t width,
2352 size_t height) -> std::unique_ptr<FlutterOpenGLTexture> {
2353 std::unique_ptr<FlutterOpenGLTexture> texture =
2354 std::make_unique<FlutterOpenGLTexture>();
2355 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2356 return nullptr;
2357 }
2358 return texture;
2359 };
2360 external_texture_resolver =
2361 std::make_unique<ExternalTextureResolver>(external_texture_callback);
2362 }
2363 }
2364#endif
2365#ifdef SHELL_ENABLE_METAL
2367 external_texture_metal_callback;
2368 if (config->type == kMetal) {
2369 const FlutterMetalRendererConfig* metal_config = &config->metal;
2370 if (SAFE_ACCESS(metal_config, external_texture_frame_callback, nullptr)) {
2371 external_texture_metal_callback =
2372 [ptr = metal_config->external_texture_frame_callback, user_data](
2373 int64_t texture_identifier, size_t width,
2374 size_t height) -> std::unique_ptr<FlutterMetalExternalTexture> {
2375 std::unique_ptr<FlutterMetalExternalTexture> texture =
2376 std::make_unique<FlutterMetalExternalTexture>();
2377 texture->struct_size = sizeof(FlutterMetalExternalTexture);
2378 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2379 return nullptr;
2380 }
2381 return texture;
2382 };
2383 external_texture_resolver = std::make_unique<ExternalTextureResolver>(
2384 external_texture_metal_callback);
2385 }
2386 }
2387#endif
2388 auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
2389 auto thread_config_callback = [&custom_task_runners](
2390 const fml::Thread::ThreadConfig& config) {
2392 if (!custom_task_runners || !custom_task_runners->thread_priority_setter) {
2393 return;
2394 }
2396 switch (config.priority) {
2399 break;
2402 break;
2405 break;
2408 break;
2409 }
2410 custom_task_runners->thread_priority_setter(priority);
2411 };
2412 auto thread_host =
2414 custom_task_runners, thread_config_callback);
2415
2416 if (!thread_host || !thread_host->IsValid()) {
2418 "Could not set up or infer thread configuration "
2419 "to run the Flutter engine on.");
2420 }
2421
2422 auto task_runners = thread_host->GetTaskRunners();
2423
2424 if (!task_runners.IsValid()) {
2426 "Task runner configuration was invalid.");
2427 }
2428
2429 // Embedder supplied UI task runner runner does not have a message loop.
2430 bool has_ui_thread_message_loop =
2431 task_runners.GetUITaskRunner()->GetTaskQueueId().is_valid();
2432 // Message loop observers are used to flush the microtask queue.
2433 // If there is no message loop the queue is flushed from
2434 // EmbedderEngine::RunTask.
2435 settings.task_observer_add = [has_ui_thread_message_loop](
2436 intptr_t key, const fml::closure& callback) {
2437 if (has_ui_thread_message_loop) {
2439 }
2441 };
2442 settings.task_observer_remove = [has_ui_thread_message_loop](
2443 fml::TaskQueueId queue_id, intptr_t key) {
2444 if (has_ui_thread_message_loop) {
2446 }
2447 };
2448
2449 auto run_configuration =
2451
2452 if (SAFE_ACCESS(args, custom_dart_entrypoint, nullptr) != nullptr) {
2453 auto dart_entrypoint = std::string{args->custom_dart_entrypoint};
2454 if (!dart_entrypoint.empty()) {
2455 run_configuration.SetEntrypoint(std::move(dart_entrypoint));
2456 }
2457 }
2458
2459 if (SAFE_ACCESS(args, dart_entrypoint_argc, 0) > 0) {
2460 if (SAFE_ACCESS(args, dart_entrypoint_argv, nullptr) == nullptr) {
2462 "Could not determine Dart entrypoint arguments "
2463 "as dart_entrypoint_argc "
2464 "was set, but dart_entrypoint_argv was null.");
2465 }
2466 std::vector<std::string> arguments(args->dart_entrypoint_argc);
2467 for (int i = 0; i < args->dart_entrypoint_argc; ++i) {
2468 arguments[i] = std::string{args->dart_entrypoint_argv[i]};
2469 }
2470 run_configuration.SetEntrypointArgs(std::move(arguments));
2471 }
2472
2473 if (SAFE_ACCESS(args, engine_id, 0) != 0) {
2474 run_configuration.SetEngineId(args->engine_id);
2475 }
2476
2477 if (!run_configuration.IsValid()) {
2478 return LOG_EMBEDDER_ERROR(
2480 "Could not infer the Flutter project to run from given arguments.");
2481 }
2482
2483 // Create the engine but don't launch the shell or run the root isolate.
2484 auto embedder_engine = std::make_unique<flutter::EmbedderEngine>(
2485 std::move(thread_host), //
2486 std::move(task_runners), //
2487 std::move(settings), //
2488 std::move(run_configuration), //
2489 on_create_platform_view, //
2490 on_create_rasterizer, //
2491 std::move(external_texture_resolver) //
2492 );
2493
2494 // Release the ownership of the embedder engine to the caller.
2495 *engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(
2496 embedder_engine.release());
2497 return kSuccess;
2498}
2499
2502 if (!engine) {
2503 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2504 }
2505
2506 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2507
2508 // The engine must not already be running. Initialize may only be called
2509 // once on an engine instance.
2510 if (embedder_engine->IsValid()) {
2511 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2512 }
2513
2514 // Step 1: Launch the shell.
2515 if (!embedder_engine->LaunchShell()) {
2517 "Could not launch the engine using supplied "
2518 "initialization arguments.");
2519 }
2520
2521 // Step 2: Tell the platform view to initialize itself.
2522 if (!embedder_engine->NotifyCreated()) {
2524 "Could not create platform view components.");
2525 }
2526
2527 // Step 3: Launch the root isolate.
2528 if (!embedder_engine->RunRootIsolate()) {
2529 return LOG_EMBEDDER_ERROR(
2531 "Could not run the root isolate of the Flutter application using the "
2532 "project arguments specified.");
2533 }
2534
2535 return kSuccess;
2536}
2537
2540 engine,
2541 const FlutterAddViewInfo* info) {
2542 if (!engine) {
2543 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2544 }
2545 if (!info || !info->view_metrics || !info->add_view_callback) {
2547 "Add view info handle was invalid.");
2548 }
2549
2552 return LOG_EMBEDDER_ERROR(
2554 "Add view info was invalid. The implicit view cannot be added.");
2555 }
2557 view_id) {
2560 "Add view info was invalid. The info and "
2561 "window metric view IDs must match.");
2562 }
2563 }
2564
2565 // TODO(loicsharma): Return an error if the engine was initialized with
2566 // callbacks that are incompatible with multiple views.
2567 // https://github.com/flutter/flutter/issues/144806
2568
2569 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2571
2572 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2573 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2574 }
2575
2576 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2577
2578 // The engine must be running to add a view.
2579 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2580 if (!embedder_engine->IsValid()) {
2581 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2582 }
2583
2585 [c_callback = info->add_view_callback,
2586 user_data = info->user_data](bool added) {
2587 FlutterAddViewResult result = {};
2588 result.struct_size = sizeof(FlutterAddViewResult);
2589 result.added = added;
2590 result.user_data = user_data;
2591 c_callback(&result);
2592 };
2593
2594 embedder_engine->GetShell().GetPlatformView()->AddView(view_id, metrics,
2595 callback);
2596 return kSuccess;
2597}
2598
2601 engine,
2602 const FlutterRemoveViewInfo* info) {
2603 if (!engine) {
2604 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2605 }
2606 if (!info || !info->remove_view_callback) {
2608 "Remove view info handle was invalid.");
2609 }
2610
2611 if (info->view_id == kFlutterImplicitViewId) {
2612 return LOG_EMBEDDER_ERROR(
2614 "Remove view info was invalid. The implicit view cannot be removed.");
2615 }
2616
2617 // TODO(loicsharma): Return an error if the engine was initialized with
2618 // callbacks that are incompatible with multiple views.
2619 // https://github.com/flutter/flutter/issues/144806
2620
2621 // The engine must be running to remove a view.
2622 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2623 if (!embedder_engine->IsValid()) {
2624 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2625 }
2626
2628 [c_callback = info->remove_view_callback,
2629 user_data = info->user_data](bool removed) {
2630 FlutterRemoveViewResult result = {};
2631 result.struct_size = sizeof(FlutterRemoveViewResult);
2632 result.removed = removed;
2633 result.user_data = user_data;
2634 c_callback(&result);
2635 };
2636
2637 embedder_engine->GetShell().GetPlatformView()->RemoveView(info->view_id,
2638 callback);
2639 return kSuccess;
2640}
2641
2644 const FlutterViewFocusEvent* event) {
2645 if (!engine) {
2646 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2647 }
2648 if (!event) {
2650 "View focus event must not be null.");
2651 }
2652 // The engine must be running to focus a view.
2653 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2654 if (!embedder_engine->IsValid()) {
2655 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2656 }
2657
2658 if (!STRUCT_HAS_MEMBER(event, direction)) {
2660 "The event struct has invalid size.");
2661 }
2662
2663 flutter::ViewFocusEvent flutter_event(
2664 event->view_id, //
2665 static_cast<flutter::ViewFocusState>(event->state),
2666 static_cast<flutter::ViewFocusDirection>(event->direction));
2667
2668 embedder_engine->GetShell().GetPlatformView()->SendViewFocusEvent(
2669 flutter_event);
2670
2671 return kSuccess;
2672}
2673
2676 engine) {
2677 if (engine == nullptr) {
2678 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2679 }
2680
2681 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2682 embedder_engine->NotifyDestroyed();
2683 embedder_engine->CollectShell();
2684 embedder_engine->CollectThreadHost();
2685 return kSuccess;
2686}
2687
2689 engine) {
2690 auto result = FlutterEngineDeinitialize(engine);
2691 if (result != kSuccess) {
2692 return result;
2693 }
2694 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2695 delete embedder_engine;
2696 return kSuccess;
2697}
2698
2701 const FlutterWindowMetricsEvent* flutter_metrics) {
2702 if (engine == nullptr || flutter_metrics == nullptr) {
2703 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2704 }
2706 SAFE_ACCESS(flutter_metrics, view_id, kFlutterImplicitViewId);
2707
2708 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2709 MakeViewportMetricsFromWindowMetrics(flutter_metrics);
2710 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2711 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2712 }
2713
2714 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2715
2716 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
2717 view_id, metrics)
2718 ? kSuccess
2720 "Viewport metrics were invalid.");
2721}
2722
2723// Returns the flutter::PointerData::Change for the given FlutterPointerPhase.
2725 FlutterPointerPhase phase) {
2726 switch (phase) {
2727 case kCancel:
2729 case kUp:
2731 case kDown:
2733 case kMove:
2735 case kAdd:
2737 case kRemove:
2739 case kHover:
2741 case kPanZoomStart:
2743 case kPanZoomUpdate:
2745 case kPanZoomEnd:
2747 }
2749}
2750
2751// Returns the flutter::PointerData::DeviceKind for the given
2752// FlutterPointerDeviceKind.
2754 FlutterPointerDeviceKind device_kind) {
2755 switch (device_kind) {
2766 }
2768}
2769
2770// Returns the flutter::PointerData::SignalKind for the given
2771// FlutterPointerSignaKind.
2774 switch (kind) {
2783 }
2785}
2786
2787// Returns the buttons to synthesize for a PointerData from a
2788// FlutterPointerEvent with no type or buttons set.
2791 switch (change) {
2794 // These kinds of change must have a non-zero `buttons`, otherwise
2795 // gesture recognizers will ignore these events.
2805 return 0;
2806 }
2807 return 0;
2808}
2809
2812 const FlutterPointerEvent* pointers,
2813 size_t events_count) {
2814 if (engine == nullptr) {
2815 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2816 }
2817
2818 if (pointers == nullptr || events_count == 0) {
2819 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid pointer events.");
2820 }
2821
2822 auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
2823
2824 const FlutterPointerEvent* current = pointers;
2825
2826 for (size_t i = 0; i < events_count; ++i) {
2827 flutter::PointerData pointer_data;
2828 pointer_data.Clear();
2829 // this is currely in use only on android embedding.
2830 pointer_data.embedder_id = 0;
2831 pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
2832 pointer_data.change = ToPointerDataChange(
2833 SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
2834 pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
2835 pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
2836 // Delta will be generated in pointer_data_packet_converter.cc.
2837 pointer_data.physical_delta_x = 0.0;
2838 pointer_data.physical_delta_y = 0.0;
2839 pointer_data.device = SAFE_ACCESS(current, device, 0);
2840 // Pointer identifier will be generated in
2841 // pointer_data_packet_converter.cc.
2842 pointer_data.pointer_identifier = 0;
2843 pointer_data.signal_kind = ToPointerDataSignalKind(
2844 SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
2845 pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
2846 pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
2847 FlutterPointerDeviceKind device_kind =
2848 SAFE_ACCESS(current, device_kind, kFlutterPointerDeviceKindMouse);
2849 // For backwards compatibility with embedders written before the device
2850 // kind and buttons were exposed, if the device kind is not set treat it
2851 // as a mouse, with a synthesized primary button state based on the phase.
2852 if (device_kind == 0) {
2854 pointer_data.buttons =
2856
2857 } else {
2858 pointer_data.kind = ToPointerDataKind(device_kind);
2859 if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
2860 // For touch events, set the button internally rather than requiring
2861 // it at the API level, since it's a confusing construction to expose.
2862 if (pointer_data.change == flutter::PointerData::Change::kDown ||
2865 }
2866 } else {
2867 // Buttons use the same mask values, so pass them through directly.
2868 pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
2869 }
2870 }
2871 pointer_data.pan_x = SAFE_ACCESS(current, pan_x, 0.0);
2872 pointer_data.pan_y = SAFE_ACCESS(current, pan_y, 0.0);
2873 // Delta will be generated in pointer_data_packet_converter.cc.
2874 pointer_data.pan_delta_x = 0.0;
2875 pointer_data.pan_delta_y = 0.0;
2876 pointer_data.scale = SAFE_ACCESS(current, scale, 0.0);
2877 pointer_data.rotation = SAFE_ACCESS(current, rotation, 0.0);
2878 pointer_data.pressure = SAFE_ACCESS(current, pressure, 0.0);
2879 pointer_data.pressure_min = SAFE_ACCESS(current, pressure_min, 0.0);
2880 pointer_data.pressure_max = SAFE_ACCESS(current, pressure_max, 0.0);
2881 pointer_data.view_id =
2883 packet->SetPointerData(i, pointer_data);
2884 current = reinterpret_cast<const FlutterPointerEvent*>(
2885 reinterpret_cast<const uint8_t*>(current) + current->struct_size);
2886 }
2887
2888 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2889 ->DispatchPointerDataPacket(std::move(packet))
2890 ? kSuccess
2892 "Could not dispatch pointer events to the "
2893 "running Flutter application.");
2894}
2895
2897 FlutterKeyEventType event_kind) {
2898 switch (event_kind) {
2905 }
2907}
2908
2910 FlutterKeyEventDeviceType event_kind) {
2911 switch (event_kind) {
2922 }
2924}
2925
2926// Send a platform message to the framework.
2927//
2928// The `data_callback` will be invoked with `user_data`, and must not be empty.
2931 const char* channel,
2932 const uint8_t* data,
2933 size_t size,
2934 FlutterDataCallback data_callback,
2935 void* user_data) {
2936 FlutterEngineResult result;
2937
2938 FlutterPlatformMessageResponseHandle* response_handle;
2940 engine, data_callback, user_data, &response_handle);
2941 if (result != kSuccess) {
2942 return result;
2943 }
2944
2946 sizeof(FlutterPlatformMessage), // struct_size
2947 channel, // channel
2948 data, // message
2949 size, // message_size
2950 response_handle, // response_handle
2951 };
2952
2954 // Whether `SendPlatformMessage` succeeds or not, the response handle must be
2955 // released.
2956 FlutterEngineResult release_result =
2958 if (result != kSuccess) {
2959 return result;
2960 }
2961
2962 return release_result;
2963}
2964
2966 engine,
2967 const FlutterKeyEvent* event,
2969 void* user_data) {
2970 if (engine == nullptr) {
2971 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2972 }
2973
2974 if (event == nullptr) {
2975 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid key event.");
2976 }
2977
2978 const char* character = SAFE_ACCESS(event, character, nullptr);
2979
2980 flutter::KeyData key_data;
2981 key_data.Clear();
2982 key_data.timestamp = static_cast<uint64_t>(SAFE_ACCESS(event, timestamp, 0));
2983 key_data.type = MapKeyEventType(
2985 key_data.physical = SAFE_ACCESS(event, physical, 0);
2986 key_data.logical = SAFE_ACCESS(event, logical, 0);
2987 key_data.synthesized = SAFE_ACCESS(event, synthesized, false);
2989 event, device_type,
2991
2992 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data, character);
2993
2994 struct MessageData {
2996 void* user_data;
2997 };
2998
2999 MessageData* message_data =
3000 new MessageData{.callback = callback, .user_data = user_data};
3001
3002 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
3004 engine, kFlutterKeyDataChannel, packet->data().data(),
3005 packet->data().size(),
3006 [](const uint8_t* data, size_t size, void* user_data) {
3007 auto message_data = std::unique_ptr<MessageData>(
3008 reinterpret_cast<MessageData*>(user_data));
3009 if (message_data->callback == nullptr) {
3010 return;
3011 }
3012 bool handled = false;
3013 if (size == 1) {
3014 handled = *data != 0;
3015 }
3016 message_data->callback(handled, message_data->user_data);
3017 },
3018 message_data);
3019}
3020
3023 const FlutterPlatformMessage* flutter_message) {
3024 if (engine == nullptr) {
3025 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3026 }
3027
3028 if (flutter_message == nullptr) {
3029 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid message argument.");
3030 }
3031
3032 if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
3033 return LOG_EMBEDDER_ERROR(
3034 kInvalidArguments, "Message argument did not specify a valid channel.");
3035 }
3036
3037 size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
3038 const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
3039
3040 if (message_size != 0 && message_data == nullptr) {
3041 return LOG_EMBEDDER_ERROR(
3043 "Message size was non-zero but the message data was nullptr.");
3044 }
3045
3046 const FlutterPlatformMessageResponseHandle* response_handle =
3047 SAFE_ACCESS(flutter_message, response_handle, nullptr);
3048
3050 if (response_handle && response_handle->message) {
3051 response = response_handle->message->response();
3052 }
3053
3054 std::unique_ptr<flutter::PlatformMessage> message;
3055 if (message_size == 0) {
3056 message = std::make_unique<flutter::PlatformMessage>(
3057 flutter_message->channel, response);
3058 } else {
3059 message = std::make_unique<flutter::PlatformMessage>(
3060 flutter_message->channel,
3061 fml::MallocMapping::Copy(message_data, message_size), response);
3062 }
3063
3064 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3065 ->SendPlatformMessage(std::move(message))
3066 ? kSuccess
3068 "Could not send a message to the running "
3069 "Flutter application.");
3070}
3071
3074 FlutterDataCallback data_callback,
3075 void* user_data,
3076 FlutterPlatformMessageResponseHandle** response_out) {
3077 if (engine == nullptr) {
3078 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3079 }
3080
3081 if (data_callback == nullptr || response_out == nullptr) {
3082 return LOG_EMBEDDER_ERROR(
3083 kInvalidArguments, "Data callback or the response handle was invalid.");
3084 }
3085
3087 [user_data, data_callback](const uint8_t* data, size_t size) {
3088 data_callback(data, size, user_data);
3089 };
3090
3091 auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
3092 ->GetTaskRunners()
3093 .GetPlatformTaskRunner();
3094
3095 auto handle = new FlutterPlatformMessageResponseHandle();
3096
3097 handle->message = std::make_unique<flutter::PlatformMessage>(
3098 "", // The channel is empty and unused as the response handle is going
3099 // to referenced directly in the |FlutterEngineSendPlatformMessage|
3100 // with the container message discarded.
3101 fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
3102 std::move(platform_task_runner), response_callback));
3103 *response_out = handle;
3104 return kSuccess;
3105}
3106
3110 if (engine == nullptr) {
3111 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3112 }
3113
3114 if (response == nullptr) {
3115 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid response handle.");
3116 }
3117 delete response;
3118 return kSuccess;
3119}
3120
3121// Note: This can execute on any thread.
3125 const uint8_t* data,
3126 size_t data_length) {
3127 if (data_length != 0 && data == nullptr) {
3128 return LOG_EMBEDDER_ERROR(
3130 "Data size was non zero but the pointer to the data was null.");
3131 }
3132
3133 auto response = handle->message->response();
3134
3135 if (response) {
3136 if (data_length == 0) {
3137 response->CompleteEmpty();
3138 } else {
3139 response->Complete(std::make_unique<fml::DataMapping>(
3140 std::vector<uint8_t>({data, data + data_length})));
3141 }
3142 }
3143
3144 delete handle;
3145
3146 return kSuccess;
3147}
3148
3151 return kSuccess;
3152}
3153
3156 int64_t texture_identifier) {
3157 if (engine == nullptr) {
3158 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3159 }
3160
3161 if (texture_identifier == 0) {
3163 "Texture identifier was invalid.");
3164 }
3165 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
3166 texture_identifier)) {
3168 "Could not register the specified texture.");
3169 }
3170 return kSuccess;
3171}
3172
3175 int64_t texture_identifier) {
3176 if (engine == nullptr) {
3177 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3178 }
3179
3180 if (texture_identifier == 0) {
3182 "Texture identifier was invalid.");
3183 }
3184
3185 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
3186 texture_identifier)) {
3188 "Could not un-register the specified texture.");
3189 }
3190
3191 return kSuccess;
3192}
3193
3196 int64_t texture_identifier) {
3197 if (engine == nullptr) {
3198 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3199 }
3200 if (texture_identifier == 0) {
3201 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid texture identifier.");
3202 }
3203 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3204 ->MarkTextureFrameAvailable(texture_identifier)) {
3205 return LOG_EMBEDDER_ERROR(
3207 "Could not mark the texture frame as being available.");
3208 }
3209 return kSuccess;
3210}
3211
3214 bool enabled) {
3215 if (engine == nullptr) {
3216 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3217 }
3218 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetSemanticsEnabled(
3219 enabled)) {
3221 "Could not update semantics state.");
3222 }
3223 return kSuccess;
3224}
3225
3229 if (engine == nullptr) {
3230 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3231 }
3232 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3233 ->SetAccessibilityFeatures(flags)) {
3235 "Could not update accessibility features.");
3236 }
3237 return kSuccess;
3238}
3239
3242 uint64_t node_id,
3244 const uint8_t* data,
3245 size_t data_length) {
3249 .node_id = node_id,
3250 .action = action,
3251 .data = data,
3252 .data_length = data_length};
3254}
3255
3258 const FlutterSendSemanticsActionInfo* info) {
3259 if (engine == nullptr) {
3260 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3261 }
3262 auto engine_action = static_cast<flutter::SemanticsAction>(info->action);
3263 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3265 info->view_id, info->node_id, engine_action,
3266 fml::MallocMapping::Copy(info->data, info->data_length))) {
3268 "Could not dispatch semantics action.");
3269 }
3270 return kSuccess;
3271}
3272
3274 engine,
3275 intptr_t baton,
3276 uint64_t frame_start_time_nanos,
3277 uint64_t frame_target_time_nanos) {
3278 if (engine == nullptr) {
3279 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3280 }
3281
3282 TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
3283
3284 auto start_time = fml::TimePoint::FromEpochDelta(
3285 fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
3286
3287 auto target_time = fml::TimePoint::FromEpochDelta(
3288 fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
3289
3290 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
3291 baton, start_time, target_time)) {
3292 return LOG_EMBEDDER_ERROR(
3294 "Could not notify the running engine instance of a Vsync event.");
3295 }
3296
3297 return kSuccess;
3298}
3299
3302 if (engine == nullptr) {
3303 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3304 }
3305
3306 TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
3307
3308 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3309 ->ReloadSystemFonts()) {
3311 "Could not reload system fonts.");
3312 }
3313
3314 return kSuccess;
3315}
3316
3318 fml::tracing::TraceEvent0("flutter", name, /*flow_id_count=*/0,
3319 /*flow_ids=*/nullptr);
3320}
3321
3322void FlutterEngineTraceEventDurationEnd(const char* name) {
3324}
3325
3326void FlutterEngineTraceEventInstant(const char* name) {
3327 fml::tracing::TraceEventInstant0("flutter", name, /*flow_id_count=*/0,
3328 /*flow_ids=*/nullptr);
3329}
3330
3334 void* baton) {
3335 if (engine == nullptr) {
3336 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3337 }
3338
3339 if (callback == nullptr) {
3341 "Render thread callback was null.");
3342 }
3343
3344 auto task = [callback, baton]() { callback(baton); };
3345
3346 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3347 ->PostRenderThreadTask(task)
3348 ? kSuccess
3350 "Could not post the render thread task.");
3351}
3352
3353uint64_t FlutterEngineGetCurrentTime() {
3355}
3356
3358 engine,
3359 const FlutterTask* task) {
3360 if (engine == nullptr) {
3361 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3362 }
3363
3365 reinterpret_cast<intptr_t>(task->runner))) {
3366 // This task came too late, the embedder has already been destroyed.
3367 // This is not an error, just ignore the task.
3368 return kSuccess;
3369 }
3370
3371 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
3372 ? kSuccess
3374 "Could not run the specified task.");
3375}
3376
3378 engine,
3379 const rapidjson::Document& document,
3380 const std::string& channel_name) {
3381 if (channel_name.empty()) {
3382 return false;
3383 }
3384
3385 rapidjson::StringBuffer buffer;
3386 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
3387
3388 if (!document.Accept(writer)) {
3389 return false;
3390 }
3391
3392 const char* message = buffer.GetString();
3393
3394 if (message == nullptr || buffer.GetSize() == 0) {
3395 return false;
3396 }
3397
3398 auto platform_message = std::make_unique<flutter::PlatformMessage>(
3399 channel_name.c_str(), // channel
3401 buffer.GetSize()), // message
3402 nullptr // response
3403 );
3404
3405 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3406 ->SendPlatformMessage(std::move(platform_message));
3407}
3408
3410 engine,
3411 const FlutterLocale** locales,
3412 size_t locales_count) {
3413 if (engine == nullptr) {
3414 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3415 }
3416
3417 if (locales_count == 0) {
3418 return kSuccess;
3419 }
3420
3421 if (locales == nullptr) {
3422 return LOG_EMBEDDER_ERROR(kInvalidArguments, "No locales were specified.");
3423 }
3424
3425 rapidjson::Document document;
3426 auto& allocator = document.GetAllocator();
3427
3428 document.SetObject();
3429 document.AddMember("method", "setLocale", allocator);
3430
3431 rapidjson::Value args(rapidjson::kArrayType);
3432 args.Reserve(locales_count * 4, allocator);
3433 for (size_t i = 0; i < locales_count; ++i) {
3434 const FlutterLocale* locale = locales[i];
3435 const char* language_code_str = SAFE_ACCESS(locale, language_code, nullptr);
3436 if (language_code_str == nullptr || ::strlen(language_code_str) == 0) {
3437 return LOG_EMBEDDER_ERROR(
3439 "Language code is required but not present in FlutterLocale.");
3440 }
3441
3442 const char* country_code_str = SAFE_ACCESS(locale, country_code, "");
3443 const char* script_code_str = SAFE_ACCESS(locale, script_code, "");
3444 const char* variant_code_str = SAFE_ACCESS(locale, variant_code, "");
3445
3446 rapidjson::Value language_code, country_code, script_code, variant_code;
3447
3448 language_code.SetString(language_code_str, allocator);
3449 country_code.SetString(country_code_str ? country_code_str : "", allocator);
3450 script_code.SetString(script_code_str ? script_code_str : "", allocator);
3451 variant_code.SetString(variant_code_str ? variant_code_str : "", allocator);
3452
3453 // Required.
3454 args.PushBack(language_code, allocator);
3455 args.PushBack(country_code, allocator);
3456 args.PushBack(script_code, allocator);
3457 args.PushBack(variant_code, allocator);
3458 }
3459 document.AddMember("args", args, allocator);
3460
3461 return DispatchJSONPlatformMessage(engine, document, "flutter/localization")
3462 ? kSuccess
3464 "Could not send message to update locale of "
3465 "a running Flutter application.");
3466}
3467
3470}
3471
3475 const FlutterEngineDartObject* object) {
3476 if (engine == nullptr) {
3477 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3478 }
3479
3480 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->IsValid()) {
3481 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine not running.");
3482 }
3483
3484 if (port == ILLEGAL_PORT) {
3486 "Attempted to post to an illegal port.");
3487 }
3488
3489 if (object == nullptr) {
3491 "Invalid Dart object to post.");
3492 }
3493
3494 Dart_CObject dart_object = {};
3495 fml::ScopedCleanupClosure typed_data_finalizer;
3496
3497 switch (object->type) {
3499 dart_object.type = Dart_CObject_kNull;
3500 break;
3502 dart_object.type = Dart_CObject_kBool;
3503 dart_object.value.as_bool = object->bool_value;
3504 break;
3506 dart_object.type = Dart_CObject_kInt32;
3507 dart_object.value.as_int32 = object->int32_value;
3508 break;
3510 dart_object.type = Dart_CObject_kInt64;
3511 dart_object.value.as_int64 = object->int64_value;
3512 break;
3514 dart_object.type = Dart_CObject_kDouble;
3515 dart_object.value.as_double = object->double_value;
3516 break;
3518 if (object->string_value == nullptr) {
3520 "kFlutterEngineDartObjectTypeString must be "
3521 "a null terminated string but was null.");
3522 }
3523 dart_object.type = Dart_CObject_kString;
3524 dart_object.value.as_string = const_cast<char*>(object->string_value);
3525 break;
3527 auto* buffer = SAFE_ACCESS(object->buffer_value, buffer, nullptr);
3528 if (buffer == nullptr) {
3530 "kFlutterEngineDartObjectTypeBuffer must "
3531 "specify a buffer but found nullptr.");
3532 }
3533 auto buffer_size = SAFE_ACCESS(object->buffer_value, buffer_size, 0);
3534 auto callback =
3535 SAFE_ACCESS(object->buffer_value, buffer_collect_callback, nullptr);
3536 auto user_data = SAFE_ACCESS(object->buffer_value, user_data, nullptr);
3537
3538 // The user has provided a callback, let them manage the lifecycle of
3539 // the underlying data. If not, copy it out from the provided buffer.
3540
3541 if (callback == nullptr) {
3542 dart_object.type = Dart_CObject_kTypedData;
3543 dart_object.value.as_typed_data.type = Dart_TypedData_kUint8;
3544 dart_object.value.as_typed_data.length = buffer_size;
3545 dart_object.value.as_typed_data.values = buffer;
3546 } else {
3547 struct ExternalTypedDataPeer {
3548 void* user_data = nullptr;
3549 VoidCallback trampoline = nullptr;
3550 };
3551 auto peer = new ExternalTypedDataPeer();
3552 peer->user_data = user_data;
3553 peer->trampoline = callback;
3554 // This finalizer is set so that in case of failure of the
3555 // Dart_PostCObject below, we collect the peer. The embedder is still
3556 // responsible for collecting the buffer in case of non-kSuccess
3557 // returns from this method. This finalizer must be released in case
3558 // of kSuccess returns from this method.
3559 typed_data_finalizer.SetClosure([peer]() {
3560 // This is the tiny object we use as the peer to the Dart call so
3561 // that we can attach the a trampoline to the embedder supplied
3562 // callback. In case of error, we need to collect this object lest
3563 // we introduce a tiny leak.
3564 delete peer;
3565 });
3566 dart_object.type = Dart_CObject_kExternalTypedData;
3567 dart_object.value.as_external_typed_data.type = Dart_TypedData_kUint8;
3568 dart_object.value.as_external_typed_data.length = buffer_size;
3569 dart_object.value.as_external_typed_data.data = buffer;
3570 dart_object.value.as_external_typed_data.peer = peer;
3571 dart_object.value.as_external_typed_data.callback =
3572 +[](void* unused_isolate_callback_data, void* peer) {
3573 auto typed_peer = reinterpret_cast<ExternalTypedDataPeer*>(peer);
3574 typed_peer->trampoline(typed_peer->user_data);
3575 delete typed_peer;
3576 };
3577 }
3578 } break;
3579 default:
3580 return LOG_EMBEDDER_ERROR(
3582 "Invalid FlutterEngineDartObjectType type specified.");
3583 }
3584
3585 if (!Dart_PostCObject(port, &dart_object)) {
3587 "Could not post the object to the Dart VM.");
3588 }
3589
3590 // On a successful call, the VM takes ownership of and is responsible for
3591 // invoking the finalizer.
3592 typed_data_finalizer.Release();
3593 return kSuccess;
3594}
3595
3597 FLUTTER_API_SYMBOL(FlutterEngine) raw_engine) {
3598 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3599 if (engine == nullptr || !engine->IsValid()) {
3600 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine was invalid.");
3601 }
3602
3603 engine->GetShell().NotifyLowMemoryWarning();
3604
3605 rapidjson::Document document;
3606 auto& allocator = document.GetAllocator();
3607
3608 document.SetObject();
3609 document.AddMember("type", "memoryPressure", allocator);
3610
3611 return DispatchJSONPlatformMessage(raw_engine, document, "flutter/system")
3612 ? kSuccess
3615 "Could not dispatch the low memory notification message.");
3616}
3617
3621 void* user_data) {
3622 if (engine == nullptr) {
3623 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3624 }
3625
3626 if (callback == nullptr) {
3628 "Invalid native thread callback.");
3629 }
3630
3631 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3632 ->PostTaskOnEngineManagedNativeThreads(
3635 })
3636 ? kSuccess
3638 "Internal error while attempting to post "
3639 "tasks to all threads.");
3640}
3641
3642namespace {
3643static bool ValidDisplayConfiguration(const FlutterEngineDisplay* displays,
3644 size_t display_count) {
3645 std::set<FlutterEngineDisplayId> display_ids;
3646 for (size_t i = 0; i < display_count; i++) {
3647 if (displays[i].single_display && display_count != 1) {
3648 return false;
3649 }
3650 display_ids.insert(displays[i].display_id);
3651 }
3652
3653 return display_ids.size() == display_count;
3654}
3655} // namespace
3656
3659 const FlutterEngineDisplaysUpdateType update_type,
3660 const FlutterEngineDisplay* embedder_displays,
3661 size_t display_count) {
3662 if (raw_engine == nullptr) {
3663 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3664 }
3665
3666 if (!ValidDisplayConfiguration(embedder_displays, display_count)) {
3667 return LOG_EMBEDDER_ERROR(
3669 "Invalid FlutterEngineDisplay configuration specified.");
3670 }
3671
3672 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3673
3674 switch (update_type) {
3676 std::vector<std::unique_ptr<flutter::Display>> displays;
3677 const auto* display = embedder_displays;
3678 for (size_t i = 0; i < display_count; i++) {
3679 displays.push_back(std::make_unique<flutter::Display>(
3680 SAFE_ACCESS(display, display_id, i), //
3681 SAFE_ACCESS(display, refresh_rate, 0), //
3682 SAFE_ACCESS(display, width, 0), //
3683 SAFE_ACCESS(display, height, 0), //
3684 SAFE_ACCESS(display, device_pixel_ratio, 1)));
3685 display = reinterpret_cast<const FlutterEngineDisplay*>(
3686 reinterpret_cast<const uint8_t*>(display) + display->struct_size);
3687 }
3688 engine->GetShell().OnDisplayUpdates(std::move(displays));
3689 return kSuccess;
3690 }
3691 default:
3692 return LOG_EMBEDDER_ERROR(
3694 "Invalid FlutterEngineDisplaysUpdateType type specified.");
3695 }
3696}
3697
3699 engine) {
3700 if (engine == nullptr) {
3701 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3702 }
3703
3704 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->ScheduleFrame()
3705 ? kSuccess
3707 "Could not schedule frame.");
3708}
3709
3713 void* user_data) {
3714 if (engine == nullptr) {
3715 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3716 }
3717
3718 if (callback == nullptr) {
3720 "Next frame callback was null.");
3721 }
3722
3723 flutter::EmbedderEngine* embedder_engine =
3724 reinterpret_cast<flutter::EmbedderEngine*>(engine);
3725
3726 fml::WeakPtr<flutter::PlatformView> weak_platform_view =
3727 embedder_engine->GetShell().GetPlatformView();
3728
3729 if (!weak_platform_view) {
3731 "Platform view unavailable.");
3732 }
3733
3734 weak_platform_view->SetNextFrameCallback(
3736
3737 return kSuccess;
3738}
3739
3741 FlutterEngineProcTable* table) {
3742 if (!table) {
3743 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null table specified.");
3744 }
3745#define SET_PROC(member, function) \
3746 if (STRUCT_HAS_MEMBER(table, member)) { \
3747 table->member = &function; \
3748 }
3749
3750 SET_PROC(CreateAOTData, FlutterEngineCreateAOTData);
3751 SET_PROC(CollectAOTData, FlutterEngineCollectAOTData);
3754 SET_PROC(Initialize, FlutterEngineInitialize);
3755 SET_PROC(Deinitialize, FlutterEngineDeinitialize);
3756 SET_PROC(RunInitialized, FlutterEngineRunInitialized);
3757 SET_PROC(SendWindowMetricsEvent, FlutterEngineSendWindowMetricsEvent);
3758 SET_PROC(SendPointerEvent, FlutterEngineSendPointerEvent);
3759 SET_PROC(SendKeyEvent, FlutterEngineSendKeyEvent);
3760 SET_PROC(SendPlatformMessage, FlutterEngineSendPlatformMessage);
3761 SET_PROC(PlatformMessageCreateResponseHandle,
3763 SET_PROC(PlatformMessageReleaseResponseHandle,
3765 SET_PROC(SendPlatformMessageResponse,
3767 SET_PROC(RegisterExternalTexture, FlutterEngineRegisterExternalTexture);
3768 SET_PROC(UnregisterExternalTexture, FlutterEngineUnregisterExternalTexture);
3769 SET_PROC(MarkExternalTextureFrameAvailable,
3771 SET_PROC(UpdateSemanticsEnabled, FlutterEngineUpdateSemanticsEnabled);
3772 SET_PROC(UpdateAccessibilityFeatures,
3774 SET_PROC(DispatchSemanticsAction, FlutterEngineDispatchSemanticsAction);
3775 SET_PROC(SendSemanticsAction, FlutterEngineSendSemanticsAction);
3777 SET_PROC(ReloadSystemFonts, FlutterEngineReloadSystemFonts);
3778 SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin);
3779 SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd);
3780 SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant);
3781 SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask);
3784 SET_PROC(UpdateLocales, FlutterEngineUpdateLocales);
3785 SET_PROC(RunsAOTCompiledDartCode, FlutterEngineRunsAOTCompiledDartCode);
3786 SET_PROC(PostDartObject, FlutterEnginePostDartObject);
3787 SET_PROC(NotifyLowMemoryWarning, FlutterEngineNotifyLowMemoryWarning);
3788 SET_PROC(PostCallbackOnAllNativeThreads,
3790 SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate);
3791 SET_PROC(ScheduleFrame, FlutterEngineScheduleFrame);
3792 SET_PROC(SetNextFrameCallback, FlutterEngineSetNextFrameCallback);
3794 SET_PROC(RemoveView, FlutterEngineRemoveView);
3795 SET_PROC(SendViewFocusEvent, FlutterEngineSendViewFocusEvent);
3796#undef SET_PROC
3797
3798 return kSuccess;
3799}
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition dart_vm.cc:177
bool DispatchSemanticsAction(int64_t view_id, int node_id, flutter::SemanticsAction action, fml::MallocMapping args)
std::function< std::unique_ptr< FlutterOpenGLTexture >(int64_t, size_t, size_t)> ExternalTextureCallback
std::function< std::unique_ptr< FlutterMetalExternalTexture >(int64_t, size_t, size_t)> ExternalTextureCallback
std::function< bool(FlutterViewId view_id, const std::vector< const FlutterLayer * > &layers)> PresentCallback
std::function< std::unique_ptr< EmbedderRenderTarget >(GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, const FlutterBackingStoreConfig &config)> CreateRenderTargetCallback
std::function< void(const uint8_t *data, size_t size)> Callback
std::function< SetCurrentResult()> MakeOrClearCurrentCallback
static bool RunnerIsValid(intptr_t runner)
static std::unique_ptr< EmbedderThreadHost > CreateEmbedderOrEngineManagedThreadHost(const FlutterCustomTaskRunners *custom_task_runners, const flutter::ThreadConfigSetter &config_setter=fml::Thread::SetCurrentThreadName)
std::function< void *(const char *)> GLProcResolver
static SkColorType ColorTypeFromFormat(const VkFormat format)
static void SetCacheDirectoryPath(std::string path)
std::function< void()> OnPreEngineRestartCallback
std::function< void(int64_t view_id, flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions)> UpdateSemanticsCallback
std::function< void(std::unique_ptr< PlatformMessage >)> PlatformMessageResponseCallback
std::function< std::unique_ptr< std::vector< std::string > >(const std::vector< std::string > &supported_locale_data)> ComputePlatformResolvedLocaleCallback
std::function< void(const std::string &, bool)> ChanneUpdateCallback
std::function< void(const ViewFocusChangeRequest &)> ViewFocusChangeRequestCallback
std::function< void(bool removed)> RemoveViewCallback
std::function< void(bool added)> AddViewCallback
static RunConfiguration InferFromSettings(const Settings &settings, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer a run configuration from the settings object. This tries to create a run configurat...
const Settings & GetSettings() const override
Definition shell.cc:912
const TaskRunners & GetTaskRunners() const override
If callers wish to interact directly with any shell subcomponents, they must (on the platform thread)...
Definition shell.cc:916
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
Definition shell.h:121
fml::WeakPtr< PlatformView > GetPlatformView()
Platform views may only be accessed on the platform task runner.
Definition shell.cc:935
std::function< void(intptr_t)> VsyncCallback
static std::unique_ptr< FileMapping > CreateReadExecute(const std::string &path)
Definition mapping.cc:44
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition mapping.cc:20
static MallocMapping Copy(const T *begin, const T *end)
Definition mapping.h:162
void RemoveTaskObserver(intptr_t key)
void AddTaskObserver(intptr_t key, const fml::closure &callback)
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
void RunExpiredTasksNow()
static fml::RefPtr< NativeLibrary > CreateForCurrentProcess()
static fml::RefPtr< NativeLibrary > Create(const char *path)
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition closure.h:32
fml::closure SetClosure(const fml::closure &closure)
Definition closure.h:55
fml::closure Release()
Definition closure.h:61
static TaskQueueId Invalid()
@ kNormal
Default priority level.
@ kRaster
Suitable for thread which raster data.
@ kBackground
Suitable for threads that shouldn't disrupt high priority work.
@ kDisplay
Suitable for threads which generate data for the display.
static void SetCurrentThreadName(const ThreadConfig &config)
Definition thread.cc:135
static constexpr TimeDelta FromNanoseconds(int64_t nanos)
Definition time_delta.h:40
constexpr int64_t ToNanoseconds() const
Definition time_delta.h:61
constexpr TimeDelta ToEpochDelta() const
Definition time_point.h:52
static TimePoint Now()
Definition time_point.cc:49
static constexpr TimePoint FromEpochDelta(TimeDelta ticks)
Definition time_point.h:43
static ContextGLES & Cast(Context &base)
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
RenderTarget & SetDepthAttachment(std::optional< DepthAttachment > attachment)
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
static std::shared_ptr< TextureGLES > WrapFBO(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, GLuint fbo)
Create a texture by wrapping an external framebuffer object whose lifecycle is owned by the caller.
static std::shared_ptr< TextureGLES > CreatePlaceholder(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc)
Create a "texture" that is never expected to be bound/unbound explicitly or initialized in any way....
int32_t x
#define SET_PROC(member, function)
void FlutterEngineTraceEventInstant(const char *name)
A profiling utility. Logs a trace duration instant event to the timeline. If the timeline is unavaila...
Definition embedder.cc:3327
static FlutterEngineResult InternalSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const char *channel, const uint8_t *data, size_t size, FlutterDataCallback data_callback, void *user_data)
Definition embedder.cc:2930
FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable(FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
Mark that a new texture frame is available for a given texture identifier.
Definition embedder.cc:3195
FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterTask *task)
Inform the engine to run the specified task. This task has been given to the embedder via the Flutter...
Definition embedder.cc:3358
FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine) engine, intptr_t baton, uint64_t frame_start_time_nanos, uint64_t frame_target_time_nanos)
Notify the engine that a vsync event occurred. A baton passed to the platform via the vsync callback ...
Definition embedder.cc:3274
const int32_t kFlutterSemanticsNodeIdBatchEnd
Definition embedder.cc:109
const int32_t kFlutterSemanticsCustomActionIdBatchEnd
Definition embedder.cc:110
static bool IsMetalRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:193
FlutterEngineResult FlutterEngineRun(size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
Initialize and run a Flutter engine instance and return a handle to it. This is a convenience method ...
Definition embedder.cc:2006
FlutterEngineResult FlutterEngineRegisterExternalTexture(FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
Register an external texture with a unique (per engine) identifier. Only rendering backends that supp...
Definition embedder.cc:3155
FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterLocale **locales, size_t locales_count)
Notify a running engine instance that the locale has been updated. The preferred locale must be the f...
Definition embedder.cc:3410
const uint8_t kPlatformStrongDill[]
FlutterEngineResult FlutterEngineSendViewFocusEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterViewFocusEvent *event)
Notifies the engine that platform view focus state has changed.
Definition embedder.cc:2643
FlutterEngineResult FlutterEngineGetProcAddresses(FlutterEngineProcTable *table)
Gets the table of engine function pointers.
Definition embedder.cc:3741
static bool DispatchJSONPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const rapidjson::Document &document, const std::string &channel_name)
Definition embedder.cc:3378
FlutterEngineResult FlutterEngineScheduleFrame(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Schedule a new frame to redraw the content.
Definition embedder.cc:3699
void FlutterEngineTraceEventDurationBegin(const char *name)
A profiling utility. Logs a trace duration begin event to the timeline. If the timeline is unavailabl...
Definition embedder.cc:3318
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:2700
flutter::PointerData::SignalKind ToPointerDataSignalKind(FlutterPointerSignalKind kind)
Definition embedder.cc:2773
uint64_t FlutterEngineGetCurrentTime()
Get the current time in nanoseconds from the clock used by the flutter engine. This is the system mon...
Definition embedder.cc:3354
static bool IsOpenGLRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:160
FlutterEngineResult FlutterEngineSetNextFrameCallback(FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, void *user_data)
Schedule a callback to be called after the next frame is drawn. This must be called from the platform...
Definition embedder.cc:3711
FlutterEngineResult __FlutterEngineFlushPendingTasksNow()
This API is only meant to be used by platforms that need to flush tasks on a message loop not control...
Definition embedder.cc:3150
#define LOG_EMBEDDER_ERROR(code, reason)
Definition embedder.cc:157
static flutter::Shell::CreateCallback< flutter::PlatformView > InferPlatformViewCreationCallback(const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
Definition embedder.cc:819
FlutterEngineResult FlutterEnginePostRenderThreadTask(FLUTTER_API_SYMBOL(FlutterEngine) engine, VoidCallback callback, void *baton)
Posts a task onto the Flutter render thread. Typically, this may be called from any thread as long as...
Definition embedder.cc:3332
static flutter::KeyEventDeviceType MapKeyEventDeviceType(FlutterKeyEventDeviceType event_kind)
Definition embedder.cc:2910
static bool IsRendererValid(const FlutterRendererConfig *config)
Definition embedder.cc:231
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 FlutterOpenGLFramebuffer *framebuffer)
Definition embedder.cc:1148
std::unique_ptr< Dart_LoadedElf, LoadedElfDeleter > UniqueLoadedElf
Definition embedder.cc:1705
static flutter::Shell::CreateCallback< flutter::PlatformView > InferOpenGLPlatformViewCreationCallback(const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
Definition embedder.cc:307
static flutter::Shell::CreateCallback< flutter::PlatformView > InferMetalPlatformViewCreationCallback(const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
Definition embedder.cc:520
FlutterEngineResult FlutterEngineDispatchSemanticsAction(FLUTTER_API_SYMBOL(FlutterEngine) engine, uint64_t node_id, FlutterSemanticsAction action, const uint8_t *data, size_t data_length)
Dispatch a semantics action to the specified semantics node in the implicit view.
Definition embedder.cc:3241
FlutterEngineResult FlutterEnginePostDartObject(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterEngineDartPort port, const FlutterEngineDartObject *object)
Posts a Dart object to specified send port. The corresponding receive port for send port can be in an...
Definition embedder.cc:3473
flutter::PointerData::DeviceKind ToPointerDataKind(FlutterPointerDeviceKind device_kind)
Definition embedder.cc:2754
FLUTTER_EXPORT FlutterEngineResult FlutterEngineDeinitialize(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Stops running the Flutter engine instance. After this call, the embedder is also guaranteed that no m...
Definition embedder.cc:2676
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore(GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLTexture *texture)
Definition embedder.cc:855
flutter::PointerData::Change ToPointerDataChange(FlutterPointerPhase phase)
Definition embedder.cc:2725
static constexpr FlutterViewId kFlutterImplicitViewId
Definition embedder.cc:112
FlutterEngineResult FlutterEnginePostCallbackOnAllNativeThreads(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterNativeThreadCallback callback, void *user_data)
Schedule a callback to be run on all engine managed threads. The engine will attempt to service this ...
Definition embedder.cc:3619
FLUTTER_EXPORT FlutterEngineResult FlutterEngineAddView(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterAddViewInfo *info)
Adds a view.
Definition embedder.cc:2540
static std::unique_ptr< flutter::EmbedderRenderTarget > MakeRenderTargetFromSkSurface(FlutterBackingStore backing_store, sk_sp< SkSurface > skia_surface, fml::closure on_release, flutter::EmbedderRenderTarget::MakeOrClearCurrentCallback on_make_current, flutter::EmbedderRenderTarget::MakeOrClearCurrentCallback on_clear_current)
Definition embedder.cc:1365
FlutterEngineResult FlutterEngineInitialize(size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
Initialize a Flutter engine instance. This does not run the Flutter application code till the Flutter...
Definition embedder.cc:2022
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)
Definition embedder.cc:1389
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV3(FlutterUpdateSemanticsCallback2 update_semantics_callback, void *user_data)
Definition embedder.cc:1944
FlutterEngineResult FlutterEngineUpdateAccessibilityFeatures(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterAccessibilityFeature flags)
Sets additional accessibility features.
Definition embedder.cc:3227
FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Shuts down a Flutter engine instance. The engine handle is no longer valid for any calls in the embed...
Definition embedder.cc:2689
FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterDataCallback data_callback, void *user_data, FlutterPlatformMessageResponseHandle **response_out)
Creates a platform message response handle that allows the embedder to set a native callback for a re...
Definition embedder.cc:3073
FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data)
Collects the AOT data.
Definition embedder.cc:1771
FlutterEngineResult FlutterEngineNotifyDisplayUpdate(FLUTTER_API_SYMBOL(FlutterEngine) raw_engine, const FlutterEngineDisplaysUpdateType update_type, const FlutterEngineDisplay *embedder_displays, size_t display_count)
Posts updates corresponding to display changes to a running engine instance.
Definition embedder.cc:3658
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition embedder.cc:3022
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition embedder.cc:3469
FlutterEngineResult FlutterEngineReloadSystemFonts(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Reloads the system fonts in engine.
Definition embedder.cc:3301
static flutter::KeyEventType MapKeyEventType(FlutterKeyEventType event_kind)
Definition embedder.cc:2897
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallback(const FlutterProjectArgs *args, void *user_data)
Definition embedder.cc:1960
static flutter::Shell::CreateCallback< flutter::PlatformView > InferSoftwarePlatformViewCreationCallback(const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder)
Definition embedder.cc:782
static fml::StatusOr< std::unique_ptr< flutter::EmbedderExternalViewEmbedder > > InferExternalViewEmbedderFromArgs(const FlutterCompositor *compositor, bool enable_impeller)
Definition embedder.cc:1548
const intptr_t kPlatformStrongDillSize
#define FLUTTER_EXPORT
Definition embedder.cc:34
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV1(FlutterUpdateSemanticsNodeCallback update_semantics_node_callback, FlutterUpdateSemanticsCustomActionCallback update_semantics_custom_action_callback, void *user_data)
Definition embedder.cc:1880
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition embedder.cc:2811
FlutterEngineResult FlutterEngineRunInitialized(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Runs an initialized engine instance. An engine can be initialized via FlutterEngineInitialize....
Definition embedder.cc:2501
static bool IsSoftwareRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:178
void PopulateJITSnapshotMappingCallbacks(const FlutterProjectArgs *args, flutter::Settings &settings)
Definition embedder.cc:1784
static flutter::Shell::CreateCallback< flutter::PlatformView > InferVulkanPlatformViewCreationCallback(const FlutterRendererConfig *config, void *user_data, const flutter::PlatformViewEmbedder::PlatformDispatchTable &platform_dispatch_table, std::unique_ptr< flutter::EmbedderExternalViewEmbedder > external_view_embedder, bool enable_impeller, impeller::Flags impeller_flags)
Definition embedder.cc:618
static bool IsVulkanRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:211
FlutterEngineResult FlutterEngineSendSemanticsAction(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterSendSemanticsActionInfo *info)
Dispatch a semantics action to the specified semantics node within a specific view.
Definition embedder.cc:3257
FlutterEngineResult FlutterEngineNotifyLowMemoryWarning(FLUTTER_API_SYMBOL(FlutterEngine) raw_engine)
Posts a low memory notification to a running engine instance. The engine will do its best to release ...
Definition embedder.cc:3597
FlutterEngineResult FlutterEngineUnregisterExternalTexture(FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
Unregister a previous texture registration.
Definition embedder.cc:3174
FlutterEngineResult FlutterEngineUpdateSemanticsEnabled(FLUTTER_API_SYMBOL(FlutterEngine) engine, bool enabled)
Enable or disable accessibility semantics.
Definition embedder.cc:3213
FlutterEngineResult FlutterEngineSendKeyEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterKeyEvent *event, FlutterKeyEventCallback callback, void *user_data)
Sends a key event to the engine. The framework will decide whether to handle this event in a synchron...
Definition embedder.cc:2966
void FlutterEngineTraceEventDurationEnd(const char *name)
A profiling utility. Logs a trace duration end event to the timeline. If the timeline is unavailable ...
Definition embedder.cc:3323
FlutterEngineResult FlutterEngineSendPlatformMessageResponse(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
Send a response from the native side to a platform message from the Dart Flutter application.
Definition embedder.cc:3123
const char * kFlutterKeyDataChannel
Definition embedder.cc:134
FLUTTER_EXPORT FlutterEngineResult FlutterEngineRemoveView(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterRemoveViewInfo *info)
Removes a view.
Definition embedder.cc:2601
int64_t PointerDataButtonsForLegacyEvent(flutter::PointerData::Change change)
Definition embedder.cc:2790
void PopulateAOTSnapshotMappingCallbacks(const FlutterProjectArgs *args, flutter::Settings &settings)
Definition embedder.cc:1827
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
Definition embedder.cc:3108
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV2(FlutterUpdateSemanticsCallback update_semantics_callback, void *user_data)
Definition embedder.cc:1929
static std::variant< flutter::ViewportMetrics, std::string > MakeViewportMetricsFromWindowMetrics(const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:1625
FlutterEngineResult FlutterEngineCreateAOTData(const FlutterEngineAOTDataSource *source, FlutterEngineAOTData *data_out)
Creates the necessary data structures to launch a Flutter Dart application in AOT mode....
Definition embedder.cc:1715
#define FLUTTER_API_SYMBOL(symbol)
Definition embedder.h:67
FlutterKeyEventDeviceType
Definition embedder.h:1407
@ kFlutterKeyEventDeviceTypeKeyboard
Definition embedder.h:1408
@ kFlutterKeyEventDeviceTypeDirectionalPad
Definition embedder.h:1409
@ kFlutterKeyEventDeviceTypeHdmi
Definition embedder.h:1412
@ kFlutterKeyEventDeviceTypeJoystick
Definition embedder.h:1411
@ kFlutterKeyEventDeviceTypeGamepad
Definition embedder.h:1410
void(* FlutterUpdateSemanticsCustomActionCallback)(const FlutterSemanticsCustomAction *, void *)
Definition embedder.h:1871
void(* FlutterUpdateSemanticsCallback)(const FlutterSemanticsUpdate *, void *)
Definition embedder.h:1875
FlutterViewFocusState
Represents the focus state of a given [FlutterView].
Definition embedder.h:1219
@ kFlutterEngineAOTDataSourceTypeElfPath
Definition embedder.h:2483
FlutterViewFocusDirection
Definition embedder.h:1200
struct _FlutterPlatformMessageResponseHandle FlutterPlatformMessageResponseHandle
Definition embedder.h:1486
@ kVulkan
Definition embedder.h:86
@ kOpenGL
Definition embedder.h:80
@ kMetal
Definition embedder.h:85
@ kSoftware
Definition embedder.h:81
void(* FlutterDataCallback)(const uint8_t *, size_t, void *)
Definition embedder.h:1508
FlutterPointerPhase
The phase of the pointer event.
Definition embedder.h:1267
@ kPanZoomUpdate
The pan/zoom updated.
Definition embedder.h:1303
@ kHover
The pointer moved while up.
Definition embedder.h:1299
@ kUp
Definition embedder.h:1275
@ kPanZoomStart
A pan/zoom started on this pointer.
Definition embedder.h:1301
@ kRemove
Definition embedder.h:1297
@ kCancel
Definition embedder.h:1268
@ kDown
Definition embedder.h:1282
@ kAdd
Definition embedder.h:1292
@ kMove
Definition embedder.h:1287
@ kPanZoomEnd
The pan/zoom ended.
Definition embedder.h:1305
FlutterAccessibilityFeature
Definition embedder.h:91
void(* FlutterNativeThreadCallback)(FlutterNativeThreadType type, void *user_data)
Definition embedder.h:2478
@ kFlutterEngineDartObjectTypeString
Definition embedder.h:2391
@ kFlutterEngineDartObjectTypeBool
Definition embedder.h:2387
@ kFlutterEngineDartObjectTypeDouble
Definition embedder.h:2390
@ kFlutterEngineDartObjectTypeInt32
Definition embedder.h:2388
@ kFlutterEngineDartObjectTypeBuffer
Definition embedder.h:2394
@ kFlutterEngineDartObjectTypeInt64
Definition embedder.h:2389
@ kFlutterEngineDartObjectTypeNull
Definition embedder.h:2386
void(* FlutterLogMessageCallback)(const char *, const char *, void *)
Definition embedder.h:2503
FlutterEngineResult
Definition embedder.h:72
@ kInternalInconsistency
Definition embedder.h:76
@ kInvalidLibraryVersion
Definition embedder.h:74
@ kInvalidArguments
Definition embedder.h:75
@ kSuccess
Definition embedder.h:73
FlutterNativeThreadType
Definition embedder.h:2459
FlutterPointerSignalKind
The type of a pointer signal.
Definition embedder.h:1345
@ kFlutterPointerSignalKindScale
Definition embedder.h:1349
@ kFlutterPointerSignalKindScrollInertiaCancel
Definition embedder.h:1348
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1347
@ kFlutterPointerSignalKindNone
Definition embedder.h:1346
void(* FlutterUpdateSemanticsNodeCallback)(const FlutterSemanticsNode *, void *)
Definition embedder.h:1867
void(* VoidCallback)(void *)
Definition embedder.h:416
FlutterEngineDisplaysUpdateType
Definition embedder.h:2373
@ kFlutterEngineDisplaysUpdateTypeStartup
Definition embedder.h:2379
FlutterThreadPriority
Valid values for priority of Thread.
Definition embedder.h:376
@ kBackground
Suitable for threads that shouldn't disrupt high priority work.
Definition embedder.h:378
@ kDisplay
Suitable for threads which generate data for the display.
Definition embedder.h:382
@ kNormal
Default priority level.
Definition embedder.h:380
@ kRaster
Suitable for thread which raster data.
Definition embedder.h:384
FlutterSemanticsAction
Definition embedder.h:122
void(* FlutterKeyEventCallback)(bool, void *)
Definition embedder.h:1482
int64_t FlutterViewId
Definition embedder.h:393
FlutterKeyEventType
Definition embedder.h:1401
@ kFlutterKeyEventTypeDown
Definition embedder.h:1403
@ kFlutterKeyEventTypeUp
Definition embedder.h:1402
@ kFlutterKeyEventTypeRepeat
Definition embedder.h:1404
void(* FlutterUpdateSemanticsCallback2)(const FlutterSemanticsUpdate2 *, void *)
Definition embedder.h:1879
int64_t FlutterEngineDartPort
Definition embedder.h:2383
@ kFlutterOpenGLTargetTypeFramebuffer
Definition embedder.h:424
@ kFlutterOpenGLTargetTypeSurface
Definition embedder.h:427
@ kFlutterOpenGLTargetTypeTexture
Definition embedder.h:421
@ kFlutterBackingStoreTypeSoftware2
Definition embedder.h:2115
@ kFlutterBackingStoreTypeMetal
Specifies a Metal backing store. This is backed by a Metal texture.
Definition embedder.h:2110
@ kFlutterBackingStoreTypeVulkan
Specifies a Vulkan backing store. This is backed by a Vulkan VkImage.
Definition embedder.h:2112
@ kFlutterBackingStoreTypeSoftware
Specified an software allocation for Flutter to render into using the CPU.
Definition embedder.h:2108
@ kFlutterBackingStoreTypeOpenGL
Definition embedder.h:2106
#define FLUTTER_ENGINE_VERSION
Definition embedder.h:70
FlutterPointerDeviceKind
The device type that created a pointer event.
Definition embedder.h:1309
@ kFlutterPointerDeviceKindTouch
Definition embedder.h:1311
@ kFlutterPointerDeviceKindInvertedStylus
Definition embedder.h:1314
@ kFlutterPointerDeviceKindTrackpad
Definition embedder.h:1313
@ kFlutterPointerDeviceKindStylus
Definition embedder.h:1312
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1310
#define SAFE_EXISTS(pointer, member)
Checks if the member exists and is non-null.
#define SAFE_ACCESS(pointer, member, default_value)
#define STRUCT_HAS_MEMBER(pointer, member)
#define SAFE_EXISTS_ONE_OF(pointer, member1, member2)
Checks if exactly one of member1 or member2 exists and is non-null.
FlutterVulkanImage * image
VkPhysicalDevice physical_device
Definition main.cc:67
VkDevice device
Definition main.cc:69
FlutterEngine engine
Definition main.cc:84
VkInstance instance
Definition main.cc:64
VkQueue queue
Definition main.cc:71
VkSurfaceKHR surface
Definition main.cc:65
const char * message
FlFramebuffer * framebuffer
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const gchar * channel
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
const char * name
Definition fuchsia.cc:50
std::shared_ptr< ImpellerAllocator > allocator
static const char * kApplicationKernelSnapshotFileName
FlTexture * texture
double y
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
impeller::Matrix DlMatrix
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
@ kPointerButtonMousePrimary
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
Definition switch_defs.h:52
@ kPointerButtonTouchContact
KeyEventType
Definition key_data.h:22
impeller::IRect32 DlIRect
ViewFocusDirection
Definition view_focus.h:22
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
Settings SettingsFromCommandLine(const fml::CommandLine &command_line, bool require_merged_platform_ui_thread)
Definition switches.cc:230
KeyEventDeviceType
Definition key_data.h:34
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
std::string JoinPaths(std::initializer_list< std::string > components)
Definition paths.cc:14
void TraceEventInstant0(TraceArg category_group, TraceArg name, size_t flow_id_count, const uint64_t *flow_ids)
void TraceEvent0(TraceArg category_group, TraceArg name, size_t flow_id_count, const uint64_t *flow_ids)
void TraceEventEnd(TraceArg name)
CommandLine CommandLineFromArgcArgv(int argc, const char *const *argv)
internal::CopyableLambda< T > MakeCopyable(T lambda)
bool IsFile(const std::string &path)
std::function< void()> closure
Definition closure.h:14
std::shared_ptr< Texture > WrapTextureMTL(TextureDescriptor desc, const void *mtl_texture, std::function< void()> deletion_proc=nullptr)
ISize64 ISize
Definition size.h:162
std::optional< SkColorInfo > getSkColorInfo(FlutterSoftwarePixelFormat pixfmt)
std::vector< FlutterEngineDisplay > * displays
std::shared_ptr< ContextGLES > context
impeller::ShaderType type
uint32_t color_type
int32_t height
int32_t width
UniqueLoadedElf loaded_elf
Definition embedder.cc:1708
const uint8_t * vm_isolate_instrs
Definition embedder.cc:1712
const uint8_t * vm_snapshot_instrs
Definition embedder.cc:1710
const uint8_t * vm_snapshot_data
Definition embedder.cc:1709
const uint8_t * vm_isolate_data
Definition embedder.cc:1711
std::unique_ptr< flutter::PlatformMessage > message
Definition embedder.cc:1694
FlutterAddViewCallback add_view_callback
Definition embedder.h:1147
FlutterViewId view_id
The identifier for the view to add. This must be unique.
Definition embedder.h:1127
const FlutterWindowMetricsEvent * view_metrics
Definition embedder.h:1132
void * user_data
The |FlutterAddViewInfo.user_data|.
Definition embedder.h:1111
bool added
True if the add view operation succeeded.
Definition embedder.h:1108
FlutterSize size
The size of the render target the engine expects to render into.
Definition embedder.h:2148
FlutterVulkanBackingStore vulkan
Definition embedder.h:2140
FlutterMetalBackingStore metal
Definition embedder.h:2138
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:2126
FlutterOpenGLBackingStore open_gl
The description of the OpenGL backing store.
Definition embedder.h:2132
FlutterSoftwareBackingStore software
The description of the software backing store.
Definition embedder.h:2134
FlutterSoftwareBackingStore2 software2
The description of the software backing store.
Definition embedder.h:2136
size_t struct_size
The size of this struct. Must be sizeof(FlutterBackingStore).
Definition embedder.h:2120
An update to whether a message channel has a listener set or not.
Definition embedder.h:1884
FlutterBackingStoreCreateCallback create_backing_store_callback
Definition embedder.h:2268
FlutterBackingStoreCollectCallback collect_backing_store_callback
Definition embedder.h:2273
A structure to represent a damage region.
Definition embedder.h:671
size_t num_rects
The number of rectangles within the damage region.
Definition embedder.h:675
size_t struct_size
The size of this struct. Must be sizeof(FlutterDamage).
Definition embedder.h:673
FlutterRect * damage
The actual damage region(s) in question.
Definition embedder.h:677
FlutterEngineAOTDataSourceType type
Definition embedder.h:2489
const char * elf_path
Absolute path to an ELF library file.
Definition embedder.h:2492
FlutterEngineDartObjectType type
Definition embedder.h:2442
const char * string_value
Definition embedder.h:2451
const FlutterEngineDartBuffer * buffer_value
Definition embedder.h:2452
Function-pointer-based versions of the APIs above.
Definition embedder.h:3763
size_t struct_size
The size of this struct. Must be sizeof(FlutterFrameInfo).
Definition embedder.h:688
FlutterUIntSize size
The size of the surface that will be backed by the fbo.
Definition embedder.h:690
FlutterSize size
The size of the layer (in physical pixels).
Definition embedder.h:2202
FlutterMetalTexture texture
Definition embedder.h:2029
FlutterMetalTextureFrameCallback external_texture_frame_callback
Definition embedder.h:915
FlutterMetalCommandQueueHandle present_command_queue
Alias for id<MTLCommandQueue>.
Definition embedder.h:900
FlutterMetalDeviceHandle device
Alias for id<MTLDevice>.
Definition embedder.h:898
FlutterMetalPresentCallback present_drawable_callback
Definition embedder.h:910
FlutterMetalTextureCallback get_next_drawable_callback
Definition embedder.h:905
FlutterMetalTextureHandle texture
Definition embedder.h:872
size_t struct_size
The size of this struct. Must be sizeof(FlutterMetalTexture).
Definition embedder.h:862
VoidCallback destruction_callback
Definition embedder.h:879
FlutterOpenGLSurface surface
Definition embedder.h:1978
FlutterOpenGLTexture texture
A texture for Flutter to render into.
Definition embedder.h:1972
FlutterOpenGLTargetType type
Definition embedder.h:1969
FlutterOpenGLFramebuffer framebuffer
Definition embedder.h:1975
ProcResolver gl_proc_resolver
Definition embedder.h:765
BoolPresentInfoCallback present_with_info
Definition embedder.h:789
TextureFrameCallback gl_external_texture_frame_callback
Definition embedder.h:770
FlutterFrameBufferWithDamageCallback populate_existing_damage
Definition embedder.h:803
TransformationCallback surface_transformation
Definition embedder.h:764
BoolCallback make_resource_current
Definition embedder.h:748
UIntFrameInfoCallback fbo_with_frame_info_callback
Definition embedder.h:778
FlutterOpenGLSurfaceCallback clear_current_callback
Definition embedder.h:601
FlutterOpenGLSurfaceCallback make_current_callback
Definition embedder.h:584
const char * channel
Definition embedder.h:1492
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition embedder.h:1354
size_t struct_size
The size of this struct. Must be sizeof(FlutterPresentInfo).
Definition embedder.h:710
A structure to represent a rectangle.
Definition embedder.h:648
double bottom
Definition embedder.h:652
double top
Definition embedder.h:650
double left
Definition embedder.h:649
double right
Definition embedder.h:651
FlutterRemoveViewCallback remove_view_callback
Definition embedder.h:1195
FlutterViewId view_id
Definition embedder.h:1178
void * user_data
The |FlutterRemoveViewInfo.user_data|.
Definition embedder.h:1159
bool removed
True if the remove view operation succeeded.
Definition embedder.h:1156
FlutterVulkanRendererConfig vulkan
Definition embedder.h:1043
FlutterMetalRendererConfig metal
Definition embedder.h:1042
FlutterSoftwareRendererConfig software
Definition embedder.h:1041
FlutterOpenGLRendererConfig open_gl
Definition embedder.h:1040
FlutterRendererType type
Definition embedder.h:1038
FlutterSemanticsNode * nodes
Definition embedder.h:1843
size_t nodes_count
The number of semantics node updates.
Definition embedder.h:1841
size_t custom_actions_count
The number of semantics custom action updates.
Definition embedder.h:1845
FlutterSemanticsCustomAction * custom_actions
Array of semantics custom actions. Has length custom_actions_count.
Definition embedder.h:1847
FlutterViewId view_id
The ID of the view that includes the node.
Definition embedder.h:2833
FlutterSemanticsAction action
The semantics action.
Definition embedder.h:2839
size_t data_length
The data length.
Definition embedder.h:2845
uint64_t node_id
The semantics node identifier.
Definition embedder.h:2836
const uint8_t * data
Data associated with the action.
Definition embedder.h:2842
double height
Definition embedder.h:636
double width
Definition embedder.h:635
VoidCallback destruction_callback
Definition embedder.h:2015
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:2006
FlutterSoftwarePixelFormat pixel_format
Definition embedder.h:2019
VoidCallback destruction_callback
Definition embedder.h:1996
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1987
SoftwareSurfacePresentCallback surface_present_callback
Definition embedder.h:1034
FlutterTaskRunner runner
Definition embedder.h:1904
double transY
vertical translation
Definition embedder.h:407
double pers2
perspective scale factor
Definition embedder.h:413
double skewX
horizontal skew factor
Definition embedder.h:399
double pers0
input x-axis perspective factor
Definition embedder.h:409
double scaleX
horizontal scale factor
Definition embedder.h:397
double skewY
vertical skew factor
Definition embedder.h:403
double scaleY
vertical scale factor
Definition embedder.h:405
double pers1
input y-axis perspective factor
Definition embedder.h:411
double transX
horizontal translation
Definition embedder.h:401
uint32_t width
Definition embedder.h:643
FlutterViewFocusState state
The focus state of the view.
Definition embedder.h:1240
FlutterViewFocusDirection direction
The direction in which the focus transitioned across [FlutterView]s.
Definition embedder.h:1243
FlutterViewId view_id
The identifier of the view that received the focus event.
Definition embedder.h:1237
size_t struct_size
The size of this struct. Must be sizeof(FlutterVulkanImage).
Definition embedder.h:935
uint32_t format
The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM).
Definition embedder.h:940
FlutterVulkanQueueHandle queue
Definition embedder.h:984
FlutterVulkanDeviceHandle device
Definition embedder.h:975
FlutterVulkanInstanceProcAddressCallback get_instance_proc_address_callback
Definition embedder.h:1013
size_t enabled_instance_extension_count
Definition embedder.h:987
uint32_t queue_family_index
The queue family index of the VkQueue supplied in the next field.
Definition embedder.h:977
FlutterVulkanImageCallback get_next_image_callback
Definition embedder.h:1017
const char ** enabled_instance_extensions
Definition embedder.h:994
const char ** enabled_device_extensions
Definition embedder.h:1005
FlutterVulkanInstanceHandle instance
Definition embedder.h:970
FlutterVulkanPresentCallback present_image_callback
Definition embedder.h:1023
FlutterVulkanPhysicalDeviceHandle physical_device
VkPhysicalDevice handle.
Definition embedder.h:972
void operator()(Dart_LoadedElf *elf)
Definition embedder.cc:1698
GPUMTLDestructionCallback destruction_callback
uint64_t synthesized
Definition key_data.h:70
KeyEventDeviceType device_type
Definition key_data.h:71
uint64_t logical
Definition key_data.h:66
uint64_t physical
Definition key_data.h:65
KeyEventType type
Definition key_data.h:64
uint64_t timestamp
Definition key_data.h:63
std::string application_kernel_asset
Definition settings.h:140
LogMessageCallback log_message_callback
Definition settings.h:319
MappingCallback isolate_snapshot_instr
Definition settings.h:123
std::function< void(const DartIsolate &)> root_isolate_create_callback
Definition settings.h:288
std::string assets_path
Definition settings.h:336
TaskObserverRemove task_observer_remove
Definition settings.h:285
MappingCallback isolate_snapshot_data
Definition settings.h:121
MappingCallback vm_snapshot_data
Definition settings.h:116
TaskObserverAdd task_observer_add
Definition settings.h:284
std::string log_tag
Definition settings.h:323
bool impeller_antialiased_lines
Definition settings.h:242
std::string icu_data_path
Definition settings.h:330
MappingCallback vm_snapshot_instr
Definition settings.h:118
MappingCallback dart_library_sources_kernel
Definition settings.h:129
int64_t old_gen_heap_size
Definition settings.h:355
The ThreadConfig is the thread info include thread name, thread priority.
Definition thread.h:35
std::shared_ptr< Texture > resolve_texture
Definition formats.h:910
LoadAction load_action
Definition formats.h:911
std::shared_ptr< Texture > texture
Definition formats.h:909
StoreAction store_action
Definition formats.h:912
static constexpr Color DarkSlateGray()
Definition color.h:423
bool antialiased_lines
When turned on DrawLine will use the experimental antialiased path.
Definition flags.h:11
bool use_sdfs
Use SDFs for rendering.
Definition flags.h:13
constexpr auto GetBottom() const
Definition rect.h:391
constexpr auto GetTop() const
Definition rect.h:387
constexpr auto GetLeft() const
Definition rect.h:385
constexpr auto GetRight() const
Definition rect.h:389
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
const uintptr_t id
#define TRACE_EVENT0(category_group, name)
#define GetCurrentTime()

◆ RAPIDJSON_HAS_STDSTRING

#define RAPIDJSON_HAS_STDSTRING   1

Definition at line 6 of file embedder.cc.

◆ SET_PROC

#define SET_PROC (   member,
  function 
)
Value:
if (STRUCT_HAS_MEMBER(table, member)) { \
table->member = &function; \
}
Dart_NativeFunction function
Definition fuchsia.cc:51

Typedef Documentation

◆ UniqueLoadedElf

using UniqueLoadedElf = std::unique_ptr<Dart_LoadedElf, LoadedElfDeleter>

Definition at line 1705 of file embedder.cc.

Function Documentation

◆ __FlutterEngineFlushPendingTasksNow()

FlutterEngineResult __FlutterEngineFlushPendingTasksNow ( )

This API is only meant to be used by platforms that need to flush tasks on a message loop not controlled by the Flutter engine.

Returns
The result of the call.

Definition at line 3150 of file embedder.cc.

3150 {
3152 return kSuccess;
3153}

References fml::MessageLoop::GetCurrent(), kSuccess, and fml::MessageLoop::RunExpiredTasksNow().

◆ CreateEmbedderRenderTarget()

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 
)
static

Definition at line 1389 of file embedder.cc.

1394 {
1395 FlutterBackingStore backing_store = {};
1396 backing_store.struct_size = sizeof(backing_store);
1397
1398 // Safe access checks on the compositor struct have been performed in
1399 // InferExternalViewEmbedderFromArgs and are not necessary here.
1400 auto c_create_callback = compositor->create_backing_store_callback;
1401 auto c_collect_callback = compositor->collect_backing_store_callback;
1402
1403 {
1404 TRACE_EVENT0("flutter", "FlutterCompositorCreateBackingStore");
1405 if (!c_create_callback(&config, &backing_store, compositor->user_data)) {
1406 FML_LOG(ERROR) << "Could not create the embedder backing store.";
1407 return nullptr;
1408 }
1409 }
1410
1411 if (backing_store.struct_size != sizeof(backing_store)) {
1412 FML_LOG(ERROR) << "Embedder modified the backing store struct size.";
1413 return nullptr;
1414 }
1415
1416 // In case we return early without creating an embedder render target, the
1417 // embedder has still given us ownership of its baton which we must return
1418 // back to it. If this method is successful, the closure is released when the
1419 // render target is eventually released.
1420 fml::ScopedCleanupClosure collect_callback(
1421 [c_collect_callback, backing_store, user_data = compositor->user_data]() {
1422 TRACE_EVENT0("flutter", "FlutterCompositorCollectBackingStore");
1423 c_collect_callback(&backing_store, user_data);
1424 });
1425
1426 // No safe access checks on the renderer are necessary since we allocated
1427 // the struct.
1428
1429 std::unique_ptr<flutter::EmbedderRenderTarget> render_target;
1430
1431 switch (backing_store.type) {
1433 switch (backing_store.open_gl.type) {
1435 auto skia_surface = MakeSkSurfaceFromBackingStore(
1436 context, config, &backing_store.open_gl.texture);
1437 render_target = MakeRenderTargetFromSkSurface(
1438 backing_store, std::move(skia_surface),
1439 collect_callback.Release());
1440 break;
1441 }
1443 if (enable_impeller) {
1445 backing_store, collect_callback.Release(), aiks_context, config,
1446 &backing_store.open_gl.framebuffer);
1447 break;
1448 } else {
1449 auto skia_surface = MakeSkSurfaceFromBackingStore(
1450 context, config, &backing_store.open_gl.framebuffer);
1451 render_target = MakeRenderTargetFromSkSurface(
1452 backing_store, std::move(skia_surface),
1453 collect_callback.Release());
1454 break;
1455 }
1456 }
1457
1459 auto on_make_current =
1461 context = backing_store.open_gl.surface.user_data]()
1463 bool invalidate_api_state = false;
1464 bool ok = callback(context, &invalidate_api_state);
1465 return {ok, invalidate_api_state};
1466 };
1467
1468 auto on_clear_current =
1470 context = backing_store.open_gl.surface.user_data]()
1472 bool invalidate_api_state = false;
1473 bool ok = callback(context, &invalidate_api_state);
1474 return {ok, invalidate_api_state};
1475 };
1476
1477 if (enable_impeller) {
1478 // TODO(https://github.com/flutter/flutter/issues/151670): Implement
1479 // GL Surface backing stores for Impeller.
1480 FML_LOG(ERROR) << "Unimplemented";
1481 break;
1482 } else {
1483 auto skia_surface = MakeSkSurfaceFromBackingStore(
1484 context, config, &backing_store.open_gl.surface);
1485
1486 render_target = MakeRenderTargetFromSkSurface(
1487 backing_store, std::move(skia_surface),
1488 collect_callback.Release(), on_make_current, on_clear_current);
1489 break;
1490 }
1491 }
1492 }
1493 break;
1494 }
1495
1497 auto skia_surface = MakeSkSurfaceFromBackingStore(
1498 context, config, &backing_store.software);
1499 render_target = MakeRenderTargetFromSkSurface(
1500 backing_store, std::move(skia_surface), collect_callback.Release());
1501 break;
1502 }
1504 auto skia_surface = MakeSkSurfaceFromBackingStore(
1505 context, config, &backing_store.software2);
1506 render_target = MakeRenderTargetFromSkSurface(
1507 backing_store, std::move(skia_surface), collect_callback.Release());
1508 break;
1509 }
1511 if (enable_impeller) {
1513 backing_store, collect_callback.Release(), aiks_context, config,
1514 &backing_store.metal);
1515 } else {
1516 auto skia_surface = MakeSkSurfaceFromBackingStore(context, config,
1517 &backing_store.metal);
1518 render_target = MakeRenderTargetFromSkSurface(
1519 backing_store, std::move(skia_surface), collect_callback.Release());
1520 }
1521 break;
1522 }
1524 if (enable_impeller) {
1525 FML_LOG(ERROR) << "Unimplemented";
1526 break;
1527 } else {
1528 auto skia_surface = MakeSkSurfaceFromBackingStore(
1529 context, config, &backing_store.vulkan);
1530 render_target = MakeRenderTargetFromSkSurface(
1531 backing_store, std::move(skia_surface), collect_callback.Release());
1532 break;
1533 }
1534 }
1535 };
1536
1537 if (!render_target) {
1538 FML_LOG(ERROR) << "Could not create a surface from an embedder provided "
1539 "render target.";
1540 }
1541 return render_target;
1542}

References callback, FlutterOpenGLSurface::clear_current_callback, FlutterCompositor::collect_backing_store_callback, context, FlutterCompositor::create_backing_store_callback, FML_LOG, FlutterOpenGLBackingStore::framebuffer, kFlutterBackingStoreTypeMetal, kFlutterBackingStoreTypeOpenGL, kFlutterBackingStoreTypeSoftware, kFlutterBackingStoreTypeSoftware2, kFlutterBackingStoreTypeVulkan, kFlutterOpenGLTargetTypeFramebuffer, kFlutterOpenGLTargetTypeSurface, kFlutterOpenGLTargetTypeTexture, FlutterOpenGLSurface::make_current_callback, MakeRenderTargetFromBackingStoreImpeller(), MakeRenderTargetFromSkSurface(), MakeSkSurfaceFromBackingStore(), FlutterBackingStore::metal, FlutterBackingStore::open_gl, fml::ScopedCleanupClosure::Release(), FlutterBackingStore::software, FlutterBackingStore::software2, FlutterBackingStore::struct_size, FlutterOpenGLBackingStore::surface, FlutterOpenGLBackingStore::texture, TRACE_EVENT0, FlutterOpenGLBackingStore::type, FlutterBackingStore::type, user_data, FlutterOpenGLSurface::user_data, FlutterCompositor::user_data, and FlutterBackingStore::vulkan.

Referenced by InferExternalViewEmbedderFromArgs().

◆ CreateEmbedderSemanticsUpdateCallback()

flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallback ( const FlutterProjectArgs args,
void *  user_data 
)

Definition at line 1960 of file embedder.cc.

1961 {
1962 // There are three variants for the embedder API's semantic update callbacks.
1963 // Create a callback that maps to the embedder's desired semantic update API.
1964 //
1965 // Handle the case where the embedder registered the callback
1966 // 'updated_semantics_callback2'
1967 if (SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr) {
1969 args->update_semantics_callback2, user_data);
1970 }
1971
1972 // Handle the case where the embedder registered the deprecated callback
1973 // 'update_semantics_callback'.
1974 if (SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr) {
1976 args->update_semantics_callback, user_data);
1977 }
1978
1979 // Handle the case where the embedder registered the deprecated callbacks
1980 // 'update_semantics_node_callback' and
1981 // 'update_semantics_custom_action_callback'.
1982 FlutterUpdateSemanticsNodeCallback update_semantics_node_callback = nullptr;
1983 if (SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr) {
1984 update_semantics_node_callback = args->update_semantics_node_callback;
1985 }
1986
1988 update_semantics_custom_action_callback = nullptr;
1989 if (SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
1990 nullptr) {
1991 update_semantics_custom_action_callback =
1992 args->update_semantics_custom_action_callback;
1993 }
1994
1995 if (update_semantics_node_callback != nullptr ||
1996 update_semantics_custom_action_callback != nullptr) {
1998 update_semantics_node_callback, update_semantics_custom_action_callback,
1999 user_data);
2000 }
2001
2002 // Handle the case where the embedder registered no callbacks.
2003 return nullptr;
2004}

References args, CreateEmbedderSemanticsUpdateCallbackV1(), CreateEmbedderSemanticsUpdateCallbackV2(), CreateEmbedderSemanticsUpdateCallbackV3(), SAFE_ACCESS, and user_data.

Referenced by FlutterEngineInitialize().

◆ CreateEmbedderSemanticsUpdateCallbackV1()

flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV1 ( FlutterUpdateSemanticsNodeCallback  update_semantics_node_callback,
FlutterUpdateSemanticsCustomActionCallback  update_semantics_custom_action_callback,
void *  user_data 
)

Definition at line 1880 of file embedder.cc.

1884 {
1885 return [update_semantics_node_callback,
1886 update_semantics_custom_action_callback, user_data](
1887 int64_t view_id, const flutter::SemanticsNodeUpdates& nodes,
1889 flutter::EmbedderSemanticsUpdate update{nodes, actions};
1890 FlutterSemanticsUpdate* update_ptr = update.get();
1891
1892 // First, queue all node and custom action updates.
1893 if (update_semantics_node_callback != nullptr) {
1894 for (size_t i = 0; i < update_ptr->nodes_count; i++) {
1895 update_semantics_node_callback(&update_ptr->nodes[i], user_data);
1896 }
1897 }
1898
1899 if (update_semantics_custom_action_callback != nullptr) {
1900 for (size_t i = 0; i < update_ptr->custom_actions_count; i++) {
1901 update_semantics_custom_action_callback(&update_ptr->custom_actions[i],
1902 user_data);
1903 }
1904 }
1905
1906 // Second, mark node and action batches completed now that all
1907 // updates are queued.
1908 if (update_semantics_node_callback != nullptr) {
1909 const FlutterSemanticsNode batch_end_sentinel = {
1910 sizeof(FlutterSemanticsNode),
1912 };
1913 update_semantics_node_callback(&batch_end_sentinel, user_data);
1914 }
1915
1916 if (update_semantics_custom_action_callback != nullptr) {
1917 const FlutterSemanticsCustomAction batch_end_sentinel = {
1920 };
1921 update_semantics_custom_action_callback(&batch_end_sentinel, user_data);
1922 }
1923 };
1924}

References FlutterSemanticsUpdate::custom_actions, FlutterSemanticsUpdate::custom_actions_count, i, kFlutterSemanticsCustomActionIdBatchEnd, kFlutterSemanticsNodeIdBatchEnd, FlutterSemanticsUpdate::nodes, FlutterSemanticsUpdate::nodes_count, user_data, and view_id.

Referenced by CreateEmbedderSemanticsUpdateCallback().

◆ CreateEmbedderSemanticsUpdateCallbackV2()

flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV2 ( FlutterUpdateSemanticsCallback  update_semantics_callback,
void *  user_data 
)

Definition at line 1929 of file embedder.cc.

1931 {
1932 return [update_semantics_callback, user_data](
1933 int64_t view_id, const flutter::SemanticsNodeUpdates& nodes,
1935 flutter::EmbedderSemanticsUpdate update{nodes, actions};
1936
1937 update_semantics_callback(update.get(), user_data);
1938 };
1939}

References user_data, and view_id.

Referenced by CreateEmbedderSemanticsUpdateCallback().

◆ CreateEmbedderSemanticsUpdateCallbackV3()

flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV3 ( FlutterUpdateSemanticsCallback2  update_semantics_callback,
void *  user_data 
)

Definition at line 1944 of file embedder.cc.

1946 {
1947 return [update_semantics_callback, user_data](
1948 int64_t view_id, const flutter::SemanticsNodeUpdates& nodes,
1950 flutter::EmbedderSemanticsUpdate2 update{view_id, nodes, actions};
1951
1952 update_semantics_callback(update.get(), user_data);
1953 };
1954}

References user_data, and view_id.

Referenced by CreateEmbedderSemanticsUpdateCallback().

◆ DispatchJSONPlatformMessage()

static bool DispatchJSONPlatformMessage ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const rapidjson::Document &  document,
const std::string &  channel_name 
)
static

Definition at line 3378 of file embedder.cc.

3381 {
3382 if (channel_name.empty()) {
3383 return false;
3384 }
3385
3386 rapidjson::StringBuffer buffer;
3387 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
3388
3389 if (!document.Accept(writer)) {
3390 return false;
3391 }
3392
3393 const char* message = buffer.GetString();
3394
3395 if (message == nullptr || buffer.GetSize() == 0) {
3396 return false;
3397 }
3398
3399 auto platform_message = std::make_unique<flutter::PlatformMessage>(
3400 channel_name.c_str(), // channel
3402 buffer.GetSize()), // message
3403 nullptr // response
3404 );
3405
3406 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3407 ->SendPlatformMessage(std::move(platform_message));
3408}

References fml::MallocMapping::Copy(), engine, and message.

Referenced by FlutterEngineNotifyLowMemoryWarning(), and FlutterEngineUpdateLocales().

◆ FlutterEngineAddView()

FLUTTER_EXPORT FlutterEngineResult FlutterEngineAddView ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterAddViewInfo info 
)

Adds a view.

        This is an asynchronous operation. The view should not be used
        until the |info.add_view_callback| is invoked with an |added|
        value of true. The embedder should prepare resources in advance
        but be ready to clean up on failure.

        A frame is scheduled if the operation succeeds.

        The callback is invoked on a thread managed by the engine. The
        embedder should re-thread if needed.

        Attempting to add the implicit view will fail and will return
        kInvalidArguments. Attempting to add a view with an already
        existing view ID will fail, and |info.add_view_callback| will be
        invoked with an |added| value of false.
Parameters
[in]engineA running engine instance.
[in]infoThe add view arguments. This can be deallocated once |FlutterEngineAddView| returns, before |add_view_callback| is invoked.
Returns
The result of starting the asynchronous operation. If kSuccess, the |add_view_callback| will be invoked.

Definition at line 2540 of file embedder.cc.

2542 {
2543 if (!engine) {
2544 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2545 }
2546 if (!info || !info->view_metrics || !info->add_view_callback) {
2548 "Add view info handle was invalid.");
2549 }
2550
2553 return LOG_EMBEDDER_ERROR(
2555 "Add view info was invalid. The implicit view cannot be added.");
2556 }
2558 view_id) {
2561 "Add view info was invalid. The info and "
2562 "window metric view IDs must match.");
2563 }
2564 }
2565
2566 // TODO(loicsharma): Return an error if the engine was initialized with
2567 // callbacks that are incompatible with multiple views.
2568 // https://github.com/flutter/flutter/issues/144806
2569
2570 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2572
2573 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2574 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2575 }
2576
2577 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2578
2579 // The engine must be running to add a view.
2580 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2581 if (!embedder_engine->IsValid()) {
2582 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2583 }
2584
2586 [c_callback = info->add_view_callback,
2587 user_data = info->user_data](bool added) {
2588 FlutterAddViewResult result = {};
2589 result.struct_size = sizeof(FlutterAddViewResult);
2590 result.added = added;
2591 result.user_data = user_data;
2592 c_callback(&result);
2593 };
2594
2595 embedder_engine->GetShell().GetPlatformView()->AddView(view_id, metrics,
2596 callback);
2597 return kSuccess;
2598}

References FlutterAddViewInfo::add_view_callback, FlutterAddViewResult::added, callback, engine, error, kFlutterImplicitViewId, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, MakeViewportMetricsFromWindowMetrics(), SAFE_ACCESS, FlutterAddViewResult::struct_size, user_data, FlutterAddViewResult::user_data, FlutterAddViewInfo::user_data, FlutterAddViewInfo::view_id, view_id, and FlutterAddViewInfo::view_metrics.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineCollectAOTData()

FlutterEngineResult FlutterEngineCollectAOTData ( FlutterEngineAOTData  data)

Collects the AOT data.

Warning
The embedder must ensure that this call is made only after all FlutterEngine instances launched using this data have been terminated, and that all of those instances were launched with the FlutterProjectArgs::shutdown_dart_vm_when_done flag set to true.
Parameters
[in]dataThe data to collect.
Returns
Returns if the AOT data was successfully collected.

Definition at line 1771 of file embedder.cc.

1771 {
1772 if (!data) {
1773 // Deleting a null object should be a no-op.
1774 return kSuccess;
1775 }
1776
1777 // Created in a unique pointer in `FlutterEngineCreateAOTData`.
1778 delete data;
1779 return kSuccess;
1780}

References kSuccess.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::AOTDataDeleter::operator()(), AOTDataDeleter::operator()(), and flutter::testing::TEST_F().

◆ FlutterEngineCreateAOTData()

FlutterEngineResult FlutterEngineCreateAOTData ( const FlutterEngineAOTDataSource source,
FlutterEngineAOTData data_out 
)

Creates the necessary data structures to launch a Flutter Dart application in AOT mode. The data may only be collected after all FlutterEngine instances launched using this data have been terminated.

Parameters
[in]sourceThe source of the AOT data.
[out]data_outThe AOT data on success. Unchanged on failure.
Returns
Returns if the AOT data could be successfully resolved.

Definition at line 1715 of file embedder.cc.

1717 {
1720 "AOT data can only be created in AOT mode.");
1721 } else if (!source) {
1722 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null source specified.");
1723 } else if (!data_out) {
1724 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null data_out specified.");
1725 }
1726
1727 switch (source->type) {
1729 if (!source->elf_path || !fml::IsFile(source->elf_path)) {
1731 "Invalid ELF path specified.");
1732 }
1733
1734 auto aot_data = std::make_unique<_FlutterEngineAOTData>();
1735 const char* error = nullptr;
1736
1737#if OS_FUCHSIA
1738 // TODO(gw280): https://github.com/flutter/flutter/issues/50285
1739 // Dart doesn't implement Dart_LoadELF on Fuchsia
1740 Dart_LoadedElf* loaded_elf = nullptr;
1741#else
1742 Dart_LoadedElf* loaded_elf =
1743 Dart_LoadELF(source->elf_path, // file path
1744 0, // file offset
1745 &error, // error (out)
1746 &aot_data->vm_isolate_data, // vm isolate data (out)
1747 &aot_data->vm_isolate_instrs // vm isolate instr (out)
1748 );
1749 if (loaded_elf != nullptr) {
1750 aot_data->vm_snapshot_data = aot_data->vm_isolate_data;
1751 aot_data->vm_snapshot_instrs = aot_data->vm_isolate_instrs;
1752 }
1753#endif
1754
1755 if (loaded_elf == nullptr) {
1757 }
1758
1759 aot_data->loaded_elf.reset(loaded_elf);
1760
1761 *data_out = aot_data.release();
1762 return kSuccess;
1763 }
1764 }
1765
1766 return LOG_EMBEDDER_ERROR(
1768 "Invalid FlutterEngineAOTDataSourceType type specified.");
1769}

References FlutterEngineAOTDataSource::elf_path, error, fml::IsFile(), flutter::DartVM::IsRunningPrecompiledCode(), kFlutterEngineAOTDataSourceTypeElfPath, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and FlutterEngineAOTDataSource::type.

Referenced by FlutterEngineGetProcAddresses(), LoadAotData(), flutter::testing::EmbedderTestContext::SetupAOTDataIfNecessary(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineDeinitialize()

FLUTTER_EXPORT FlutterEngineResult FlutterEngineDeinitialize ( FLUTTER_API_SYMBOL(FlutterEngine engine)

Stops running the Flutter engine instance. After this call, the embedder is also guaranteed that no more calls to post tasks onto custom task runners specified by the embedder are made. The Flutter engine handle still needs to be collected via a call to FlutterEngineShutdown.

Parameters
[in]engineThe running engine instance to de-initialize.
Returns
The result of the call to de-initialize the Flutter engine.

Definition at line 2676 of file embedder.cc.

2677 {
2678 if (engine == nullptr) {
2679 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2680 }
2681
2682 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2683 embedder_engine->NotifyDestroyed();
2684 embedder_engine->CollectShell();
2685 embedder_engine->CollectThreadHost();
2686 return kSuccess;
2687}

References engine, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and flutter::EmbedderEngine::NotifyDestroyed().

Referenced by FlutterEngineGetProcAddresses(), FlutterEngineShutdown(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_P().

◆ FlutterEngineDispatchSemanticsAction()

FlutterEngineResult FlutterEngineDispatchSemanticsAction ( FLUTTER_API_SYMBOL(FlutterEngine engine,
uint64_t  node_id,
FlutterSemanticsAction  action,
const uint8_t *  data,
size_t  data_length 
)

Dispatch a semantics action to the specified semantics node in the implicit view.

Parameters
[in]engineA running engine instance.
[in]node_idThe semantics node identifier.
[in]actionThe semantics action.
[in]dataData associated with the action.
[in]data_lengthThe data length.
Returns
The result of the call.

Definition at line 3241 of file embedder.cc.

3246 {
3250 .node_id = node_id,
3251 .action = action,
3252 .data = data,
3253 .data_length = data_length};
3255}

References action, engine, FlutterEngineSendSemanticsAction(), kFlutterImplicitViewId, FlutterSendSemanticsActionInfo::struct_size, and view_id.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineGetCurrentTime()

uint64_t FlutterEngineGetCurrentTime ( )

Get the current time in nanoseconds from the clock used by the flutter engine. This is the system monotonic clock.

Returns
The current time in nanoseconds.

Definition at line 3354 of file embedder.cc.

3354 {
3356}

References fml::TimePoint::Now(), fml::TimePoint::ToEpochDelta(), and fml::TimeDelta::ToNanoseconds().

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST(), and flutter::EventLoop::TimePointFromFlutterTime().

◆ FlutterEngineGetProcAddresses()

FlutterEngineResult FlutterEngineGetProcAddresses ( FlutterEngineProcTable table)

Gets the table of engine function pointers.

Parameters
[out]tableThe table to fill with pointers. This should be zero-initialized, except for struct_size.
Returns
Returns whether the table was successfully populated.

Definition at line 3741 of file embedder.cc.

3742 {
3743 if (!table) {
3744 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null table specified.");
3745 }
3746#define SET_PROC(member, function) \
3747 if (STRUCT_HAS_MEMBER(table, member)) { \
3748 table->member = &function; \
3749 }
3750
3751 SET_PROC(CreateAOTData, FlutterEngineCreateAOTData);
3752 SET_PROC(CollectAOTData, FlutterEngineCollectAOTData);
3755 SET_PROC(Initialize, FlutterEngineInitialize);
3756 SET_PROC(Deinitialize, FlutterEngineDeinitialize);
3757 SET_PROC(RunInitialized, FlutterEngineRunInitialized);
3758 SET_PROC(SendWindowMetricsEvent, FlutterEngineSendWindowMetricsEvent);
3759 SET_PROC(SendPointerEvent, FlutterEngineSendPointerEvent);
3760 SET_PROC(SendKeyEvent, FlutterEngineSendKeyEvent);
3761 SET_PROC(SendPlatformMessage, FlutterEngineSendPlatformMessage);
3762 SET_PROC(PlatformMessageCreateResponseHandle,
3764 SET_PROC(PlatformMessageReleaseResponseHandle,
3766 SET_PROC(SendPlatformMessageResponse,
3768 SET_PROC(RegisterExternalTexture, FlutterEngineRegisterExternalTexture);
3769 SET_PROC(UnregisterExternalTexture, FlutterEngineUnregisterExternalTexture);
3770 SET_PROC(MarkExternalTextureFrameAvailable,
3772 SET_PROC(UpdateSemanticsEnabled, FlutterEngineUpdateSemanticsEnabled);
3773 SET_PROC(UpdateAccessibilityFeatures,
3775 SET_PROC(DispatchSemanticsAction, FlutterEngineDispatchSemanticsAction);
3776 SET_PROC(SendSemanticsAction, FlutterEngineSendSemanticsAction);
3778 SET_PROC(ReloadSystemFonts, FlutterEngineReloadSystemFonts);
3779 SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin);
3780 SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd);
3781 SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant);
3782 SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask);
3785 SET_PROC(UpdateLocales, FlutterEngineUpdateLocales);
3786 SET_PROC(RunsAOTCompiledDartCode, FlutterEngineRunsAOTCompiledDartCode);
3787 SET_PROC(PostDartObject, FlutterEnginePostDartObject);
3788 SET_PROC(NotifyLowMemoryWarning, FlutterEngineNotifyLowMemoryWarning);
3789 SET_PROC(PostCallbackOnAllNativeThreads,
3791 SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate);
3792 SET_PROC(ScheduleFrame, FlutterEngineScheduleFrame);
3793 SET_PROC(SetNextFrameCallback, FlutterEngineSetNextFrameCallback);
3795 SET_PROC(RemoveView, FlutterEngineRemoveView);
3796 SET_PROC(SendViewFocusEvent, FlutterEngineSendViewFocusEvent);
3797#undef SET_PROC
3798
3799 return kSuccess;
3800}

References FlutterEngineAddView(), FlutterEngineCollectAOTData(), FlutterEngineCreateAOTData(), FlutterEngineDeinitialize(), FlutterEngineDispatchSemanticsAction(), FlutterEngineGetCurrentTime(), FlutterEngineInitialize(), FlutterEngineMarkExternalTextureFrameAvailable(), FlutterEngineNotifyDisplayUpdate(), FlutterEngineNotifyLowMemoryWarning(), FlutterEngineOnVsync(), FlutterEnginePostCallbackOnAllNativeThreads(), FlutterEnginePostDartObject(), FlutterEnginePostRenderThreadTask(), FlutterEngineRegisterExternalTexture(), FlutterEngineReloadSystemFonts(), FlutterEngineRemoveView(), FlutterEngineRun(), FlutterEngineRunInitialized(), FlutterEngineRunsAOTCompiledDartCode(), FlutterEngineRunTask(), FlutterEngineScheduleFrame(), FlutterEngineSendKeyEvent(), FlutterEngineSendPlatformMessage(), FlutterEngineSendPlatformMessageResponse(), FlutterEngineSendPointerEvent(), FlutterEngineSendSemanticsAction(), FlutterEngineSendViewFocusEvent(), FlutterEngineSendWindowMetricsEvent(), FlutterEngineSetNextFrameCallback(), FlutterEngineShutdown(), FlutterEngineTraceEventDurationBegin(), FlutterEngineTraceEventDurationEnd(), FlutterEngineTraceEventInstant(), FlutterEngineUnregisterExternalTexture(), FlutterEngineUpdateAccessibilityFeatures(), FlutterEngineUpdateLocales(), FlutterEngineUpdateSemanticsEnabled(), FlutterPlatformMessageCreateResponseHandle(), FlutterPlatformMessageReleaseResponseHandle(), GetCurrentTime, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and SET_PROC.

Referenced by fl_engine_init(), flutter::FlutterWindowsEngine::FlutterWindowsEngine(), flutter::testing::TEST(), flutter::testing::TEST(), and flutter::testing::TEST().

◆ FlutterEngineInitialize()

FlutterEngineResult FlutterEngineInitialize ( size_t  version,
const FlutterRendererConfig config,
const FlutterProjectArgs args,
void *  user_data,
FLUTTER_API_SYMBOL(FlutterEngine) *  engine_out 
)

Initialize a Flutter engine instance. This does not run the Flutter application code till the FlutterEngineRunInitialized call is made. Besides Flutter application code, no tasks are scheduled on embedder managed task runners either. This allows embedders providing custom task runners to the Flutter engine to obtain a handle to the Flutter engine before the engine can post tasks on these task runners.

Parameters
[in]versionThe Flutter embedder API version. Must be FLUTTER_ENGINE_VERSION.
[in]configThe renderer configuration.
[in]argsThe Flutter project arguments.
user_dataA user data baton passed back to embedders in callbacks.
[out]engine_outThe engine handle on successful engine creation.
Returns
The result of the call to initialize the Flutter engine.

Definition at line 2022 of file embedder.cc.

2027 {
2028 // Step 0: Figure out arguments for shell creation.
2029 if (version != FLUTTER_ENGINE_VERSION) {
2030 return LOG_EMBEDDER_ERROR(
2032 "Flutter embedder version mismatch. There has been a breaking change. "
2033 "Please consult the changelog and update the embedder.");
2034 }
2035
2036 if (engine_out == nullptr) {
2038 "The engine out parameter was missing.");
2039 }
2040
2041 if (args == nullptr) {
2043 "The Flutter project arguments were missing.");
2044 }
2045
2046 if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr) {
2047 return LOG_EMBEDDER_ERROR(
2049 "The assets path in the Flutter project arguments was missing.");
2050 }
2051
2052 if (SAFE_ACCESS(args, main_path__unused__, nullptr) != nullptr) {
2053 FML_LOG(WARNING)
2054 << "FlutterProjectArgs.main_path is deprecated and should be set null.";
2055 }
2056
2057 if (SAFE_ACCESS(args, packages_path__unused__, nullptr) != nullptr) {
2058 FML_LOG(WARNING) << "FlutterProjectArgs.packages_path is deprecated and "
2059 "should be set null.";
2060 }
2061
2062 if (!IsRendererValid(config)) {
2064 "The renderer configuration was invalid.");
2065 }
2066
2067 std::string icu_data_path;
2068 if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) {
2069 icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr);
2070 }
2071
2072#if !SLIMPELLER
2073 if (SAFE_ACCESS(args, persistent_cache_path, nullptr) != nullptr) {
2074 std::string persistent_cache_path =
2075 SAFE_ACCESS(args, persistent_cache_path, nullptr);
2077 }
2078
2079 if (SAFE_ACCESS(args, is_persistent_cache_read_only, false)) {
2081 }
2082#endif // !SLIMPELLER
2083
2084 fml::CommandLine command_line;
2085 if (SAFE_ACCESS(args, command_line_argc, 0) != 0 &&
2086 SAFE_ACCESS(args, command_line_argv, nullptr) != nullptr) {
2087 command_line = fml::CommandLineFromArgcArgv(
2088 SAFE_ACCESS(args, command_line_argc, 0),
2089 SAFE_ACCESS(args, command_line_argv, nullptr));
2090 }
2091
2092 flutter::Settings settings = flutter::SettingsFromCommandLine(command_line);
2093
2094 if (SAFE_ACCESS(args, aot_data, nullptr)) {
2095 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) ||
2096 SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) ||
2097 SAFE_ACCESS(args, isolate_snapshot_data, nullptr) ||
2098 SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr)) {
2099 return LOG_EMBEDDER_ERROR(
2101 "Multiple AOT sources specified. Embedders should provide either "
2102 "*_snapshot_* buffers or aot_data, not both.");
2103 }
2104 }
2105
2108 } else {
2110 }
2111
2112 settings.icu_data_path = icu_data_path;
2113 settings.assets_path = args->assets_path;
2114 settings.leak_vm = !SAFE_ACCESS(args, shutdown_dart_vm_when_done, false);
2115 settings.old_gen_heap_size = SAFE_ACCESS(args, dart_old_gen_heap_size, -1);
2116 settings.enable_wide_gamut = SAFE_ACCESS(args, enable_wide_gamut, false);
2117
2119 // Verify the assets path contains Dart 2 kernel assets.
2120 const std::string kApplicationKernelSnapshotFileName = "kernel_blob.bin";
2121 std::string application_kernel_path = fml::paths::JoinPaths(
2123 if (!fml::IsFile(application_kernel_path)) {
2124 return LOG_EMBEDDER_ERROR(
2126 "Not running in AOT mode but could not resolve the kernel binary.");
2127 }
2129 }
2130
2131 if (SAFE_ACCESS(args, root_isolate_create_callback, nullptr) != nullptr) {
2133 SAFE_ACCESS(args, root_isolate_create_callback, nullptr);
2135 [callback, user_data](const auto& isolate) { callback(user_data); };
2136 }
2137
2138 // Wire up callback for engine and print logging.
2139 if (SAFE_ACCESS(args, log_message_callback, nullptr) != nullptr) {
2141 SAFE_ACCESS(args, log_message_callback, nullptr);
2143 const std::string& tag,
2144 const std::string& message) {
2145 callback(tag.c_str(), message.c_str(), user_data);
2146 };
2147 } else {
2148 settings.log_message_callback = [](const std::string& tag,
2149 const std::string& message) {
2150 // Fall back to logging to stdout if unspecified.
2151 if (tag.empty()) {
2152 std::cout << tag << ": ";
2153 }
2154 std::cout << message << std::endl;
2155 };
2156 }
2157
2158 if (SAFE_ACCESS(args, log_tag, nullptr) != nullptr) {
2159 settings.log_tag = SAFE_ACCESS(args, log_tag, nullptr);
2160 }
2161
2162 bool has_update_semantics_2_callback =
2163 SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr;
2164 bool has_update_semantics_callback =
2165 SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr;
2166 bool has_legacy_update_semantics_callback =
2167 SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr ||
2168 SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
2169 nullptr;
2170
2171 int semantic_callback_count = (has_update_semantics_2_callback ? 1 : 0) +
2172 (has_update_semantics_callback ? 1 : 0) +
2173 (has_legacy_update_semantics_callback ? 1 : 0);
2174
2175 if (semantic_callback_count > 1) {
2176 return LOG_EMBEDDER_ERROR(
2178 "Multiple semantics update callbacks provided. "
2179 "Embedders should provide either `update_semantics_callback2`, "
2180 "`update_semantics_callback`, or both "
2181 "`update_semantics_node_callback` and "
2182 "`update_semantics_custom_action_callback`.");
2183 }
2184
2186 update_semantics_callback =
2188
2190 platform_message_response_callback = nullptr;
2191 if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) {
2192 platform_message_response_callback =
2193 [ptr = args->platform_message_callback,
2194 user_data](std::unique_ptr<flutter::PlatformMessage> message) {
2195 auto handle = new FlutterPlatformMessageResponseHandle();
2196 const FlutterPlatformMessage incoming_message = {
2197 sizeof(FlutterPlatformMessage), // struct_size
2198 message->channel().c_str(), // channel
2199 message->data().GetMapping(), // message
2200 message->data().GetSize(), // message_size
2201 handle, // response_handle
2202 };
2203 handle->message = std::move(message);
2204 return ptr(&incoming_message, user_data);
2205 };
2206 }
2207
2208 flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr;
2209 if (SAFE_ACCESS(args, vsync_callback, nullptr) != nullptr) {
2210 vsync_callback = [ptr = args->vsync_callback, user_data](intptr_t baton) {
2211 return ptr(user_data, baton);
2212 };
2213 }
2214
2216 compute_platform_resolved_locale_callback = nullptr;
2217 if (SAFE_ACCESS(args, compute_platform_resolved_locale_callback, nullptr) !=
2218 nullptr) {
2219 compute_platform_resolved_locale_callback =
2220 [ptr = args->compute_platform_resolved_locale_callback](
2221 const std::vector<std::string>& supported_locales_data) {
2222 const size_t number_of_strings_per_locale = 3;
2223 size_t locale_count =
2224 supported_locales_data.size() / number_of_strings_per_locale;
2225 std::vector<FlutterLocale> supported_locales;
2226 std::vector<const FlutterLocale*> supported_locales_ptr;
2227 for (size_t i = 0; i < locale_count; ++i) {
2228 supported_locales.push_back(
2229 {.struct_size = sizeof(FlutterLocale),
2230 .language_code =
2231 supported_locales_data[i * number_of_strings_per_locale +
2232 0]
2233 .c_str(),
2234 .country_code =
2235 supported_locales_data[i * number_of_strings_per_locale +
2236 1]
2237 .c_str(),
2238 .script_code =
2239 supported_locales_data[i * number_of_strings_per_locale +
2240 2]
2241 .c_str(),
2242 .variant_code = nullptr});
2243 supported_locales_ptr.push_back(&supported_locales[i]);
2244 }
2245
2246 const FlutterLocale* result =
2247 ptr(supported_locales_ptr.data(), locale_count);
2248
2249 std::unique_ptr<std::vector<std::string>> out =
2250 std::make_unique<std::vector<std::string>>();
2251 if (result) {
2252 std::string language_code(SAFE_ACCESS(result, language_code, ""));
2253 if (language_code != "") {
2254 out->push_back(language_code);
2255 out->emplace_back(SAFE_ACCESS(result, country_code, ""));
2256 out->emplace_back(SAFE_ACCESS(result, script_code, ""));
2257 }
2258 }
2259 return out;
2260 };
2261 }
2262
2264 on_pre_engine_restart_callback = nullptr;
2265 if (SAFE_ACCESS(args, on_pre_engine_restart_callback, nullptr) != nullptr) {
2266 on_pre_engine_restart_callback = [ptr =
2267 args->on_pre_engine_restart_callback,
2268 user_data]() { return ptr(user_data); };
2269 }
2270
2272 nullptr;
2273 if (SAFE_ACCESS(args, channel_update_callback, nullptr) != nullptr) {
2274 channel_update_callback = [ptr = args->channel_update_callback, user_data](
2275 const std::string& name, bool listening) {
2276 FlutterChannelUpdate update{sizeof(FlutterChannelUpdate), name.c_str(),
2277 listening};
2278 ptr(&update, user_data);
2279 };
2280 }
2281
2283 view_focus_change_request_callback = nullptr;
2284 if (SAFE_ACCESS(args, view_focus_change_request_callback, nullptr) !=
2285 nullptr) {
2286 view_focus_change_request_callback =
2287 [ptr = args->view_focus_change_request_callback,
2289 FlutterViewFocusChangeRequest embedder_request{
2291 .view_id = request.view_id(),
2292 .state = static_cast<FlutterViewFocusState>(request.state()),
2293 .direction =
2294 static_cast<FlutterViewFocusDirection>(request.direction()),
2295 };
2296 ptr(&embedder_request, user_data);
2297 };
2298 }
2299
2300 auto external_view_embedder_result = InferExternalViewEmbedderFromArgs(
2301 SAFE_ACCESS(args, compositor, nullptr), settings.enable_impeller);
2302 if (!external_view_embedder_result.ok()) {
2303 FML_LOG(ERROR) << external_view_embedder_result.status().message();
2305 "Compositor arguments were invalid.");
2306 }
2307
2309 {
2310 update_semantics_callback, //
2311 platform_message_response_callback, //
2312 vsync_callback, //
2313 compute_platform_resolved_locale_callback, //
2314 on_pre_engine_restart_callback, //
2315 channel_update_callback, //
2316 view_focus_change_request_callback, //
2317 };
2318
2319 impeller::Flags impeller_flags;
2320 impeller_flags.use_sdfs = settings.impeller_use_sdfs;
2321 impeller_flags.antialiased_lines = settings.impeller_antialiased_lines;
2322
2323 auto on_create_platform_view = InferPlatformViewCreationCallback(
2324 config, user_data, platform_dispatch_table,
2325 std::move(external_view_embedder_result.value()),
2326 settings.enable_impeller, impeller_flags);
2327
2328 if (!on_create_platform_view) {
2329 return LOG_EMBEDDER_ERROR(
2331 "Could not infer platform view creation callback.");
2332 }
2333
2335 [](flutter::Shell& shell) {
2336 return std::make_unique<flutter::Rasterizer>(shell);
2337 };
2338
2339 using ExternalTextureResolver = flutter::EmbedderExternalTextureResolver;
2340 std::unique_ptr<ExternalTextureResolver> external_texture_resolver;
2341 external_texture_resolver = std::make_unique<ExternalTextureResolver>();
2342
2343#ifdef SHELL_ENABLE_GL
2345 external_texture_callback;
2346 if (config->type == kOpenGL) {
2347 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
2348 if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
2349 nullptr) != nullptr) {
2350 external_texture_callback =
2351 [ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
2352 int64_t texture_identifier, size_t width,
2353 size_t height) -> std::unique_ptr<FlutterOpenGLTexture> {
2354 std::unique_ptr<FlutterOpenGLTexture> texture =
2355 std::make_unique<FlutterOpenGLTexture>();
2356 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2357 return nullptr;
2358 }
2359 return texture;
2360 };
2361 external_texture_resolver =
2362 std::make_unique<ExternalTextureResolver>(external_texture_callback);
2363 }
2364 }
2365#endif
2366#ifdef SHELL_ENABLE_METAL
2368 external_texture_metal_callback;
2369 if (config->type == kMetal) {
2370 const FlutterMetalRendererConfig* metal_config = &config->metal;
2371 if (SAFE_ACCESS(metal_config, external_texture_frame_callback, nullptr)) {
2372 external_texture_metal_callback =
2373 [ptr = metal_config->external_texture_frame_callback, user_data](
2374 int64_t texture_identifier, size_t width,
2375 size_t height) -> std::unique_ptr<FlutterMetalExternalTexture> {
2376 std::unique_ptr<FlutterMetalExternalTexture> texture =
2377 std::make_unique<FlutterMetalExternalTexture>();
2378 texture->struct_size = sizeof(FlutterMetalExternalTexture);
2379 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2380 return nullptr;
2381 }
2382 return texture;
2383 };
2384 external_texture_resolver = std::make_unique<ExternalTextureResolver>(
2385 external_texture_metal_callback);
2386 }
2387 }
2388#endif
2389 auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
2390 auto thread_config_callback = [&custom_task_runners](
2391 const fml::Thread::ThreadConfig& config) {
2393 if (!custom_task_runners || !custom_task_runners->thread_priority_setter) {
2394 return;
2395 }
2397 switch (config.priority) {
2400 break;
2403 break;
2406 break;
2409 break;
2410 }
2411 custom_task_runners->thread_priority_setter(priority);
2412 };
2413 auto thread_host =
2415 custom_task_runners, thread_config_callback);
2416
2417 if (!thread_host || !thread_host->IsValid()) {
2419 "Could not set up or infer thread configuration "
2420 "to run the Flutter engine on.");
2421 }
2422
2423 auto task_runners = thread_host->GetTaskRunners();
2424
2425 if (!task_runners.IsValid()) {
2427 "Task runner configuration was invalid.");
2428 }
2429
2430 // Embedder supplied UI task runner runner does not have a message loop.
2431 bool has_ui_thread_message_loop =
2432 task_runners.GetUITaskRunner()->GetTaskQueueId().is_valid();
2433 // Message loop observers are used to flush the microtask queue.
2434 // If there is no message loop the queue is flushed from
2435 // EmbedderEngine::RunTask.
2436 settings.task_observer_add = [has_ui_thread_message_loop](
2437 intptr_t key, const fml::closure& callback) {
2438 if (has_ui_thread_message_loop) {
2440 }
2442 };
2443 settings.task_observer_remove = [has_ui_thread_message_loop](
2444 fml::TaskQueueId queue_id, intptr_t key) {
2445 if (has_ui_thread_message_loop) {
2447 }
2448 };
2449
2450 auto run_configuration =
2452
2453 if (SAFE_ACCESS(args, custom_dart_entrypoint, nullptr) != nullptr) {
2454 auto dart_entrypoint = std::string{args->custom_dart_entrypoint};
2455 if (!dart_entrypoint.empty()) {
2456 run_configuration.SetEntrypoint(std::move(dart_entrypoint));
2457 }
2458 }
2459
2460 if (SAFE_ACCESS(args, dart_entrypoint_argc, 0) > 0) {
2461 if (SAFE_ACCESS(args, dart_entrypoint_argv, nullptr) == nullptr) {
2463 "Could not determine Dart entrypoint arguments "
2464 "as dart_entrypoint_argc "
2465 "was set, but dart_entrypoint_argv was null.");
2466 }
2467 std::vector<std::string> arguments(args->dart_entrypoint_argc);
2468 for (int i = 0; i < args->dart_entrypoint_argc; ++i) {
2469 arguments[i] = std::string{args->dart_entrypoint_argv[i]};
2470 }
2471 run_configuration.SetEntrypointArgs(std::move(arguments));
2472 }
2473
2474 if (SAFE_ACCESS(args, engine_id, 0) != 0) {
2475 run_configuration.SetEngineId(args->engine_id);
2476 }
2477
2478 if (!run_configuration.IsValid()) {
2479 return LOG_EMBEDDER_ERROR(
2481 "Could not infer the Flutter project to run from given arguments.");
2482 }
2483
2484 // Create the engine but don't launch the shell or run the root isolate.
2485 auto embedder_engine = std::make_unique<flutter::EmbedderEngine>(
2486 std::move(thread_host), //
2487 std::move(task_runners), //
2488 std::move(settings), //
2489 std::move(run_configuration), //
2490 on_create_platform_view, //
2491 on_create_rasterizer, //
2492 std::move(external_texture_resolver) //
2493 );
2494
2495 // Release the ownership of the embedder engine to the caller.
2496 *engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(
2497 embedder_engine.release());
2498 return kSuccess;
2499}

References fml::MessageLoop::AddTaskObserver(), impeller::Flags::antialiased_lines, flutter::Settings::application_kernel_asset, args, flutter::Settings::assets_path, callback, FlutterPlatformMessage::channel, fml::CommandLineFromArgcArgv(), flutter::EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(), CreateEmbedderSemanticsUpdateCallback(), flutter::Settings::enable_impeller, flutter::Settings::enable_wide_gamut, FlutterMetalRendererConfig::external_texture_frame_callback, FLUTTER_API_SYMBOL, FLUTTER_ENGINE_VERSION, FML_LOG, fml::MessageLoop::GetCurrent(), flutter::PersistentCache::gIsReadOnly, FlutterOpenGLRendererConfig::gl_external_texture_frame_callback, height, i, flutter::Settings::icu_data_path, flutter::Settings::impeller_antialiased_lines, flutter::Settings::impeller_use_sdfs, InferExternalViewEmbedderFromArgs(), flutter::RunConfiguration::InferFromSettings(), InferPlatformViewCreationCallback(), fml::TaskQueueId::Invalid(), fml::IsFile(), IsRendererValid(), flutter::DartVM::IsRunningPrecompiledCode(), fml::paths::JoinPaths(), kApplicationKernelSnapshotFileName, fml::Thread::kBackground, kBackground, fml::Thread::kDisplay, kDisplay, key, kInternalInconsistency, kInvalidArguments, kInvalidLibraryVersion, kMetal, fml::Thread::kNormal, kNormal, kOpenGL, fml::Thread::kRaster, kRaster, kSuccess, flutter::Settings::leak_vm, LOG_EMBEDDER_ERROR, flutter::Settings::log_message_callback, flutter::Settings::log_tag, message, FlutterRendererConfig::metal, name, flutter::Settings::old_gen_heap_size, FlutterRendererConfig::open_gl, PopulateAOTSnapshotMappingCallbacks(), PopulateJITSnapshotMappingCallbacks(), fml::MessageLoop::RemoveTaskObserver(), flutter::Settings::root_isolate_create_callback, SAFE_ACCESS, flutter::PersistentCache::SetCacheDirectoryPath(), fml::Thread::SetCurrentThreadName(), flutter::SettingsFromCommandLine(), FlutterViewFocusChangeRequest::struct_size, flutter::Settings::task_observer_add, flutter::Settings::task_observer_remove, texture, FlutterRendererConfig::type, impeller::Flags::use_sdfs, user_data, view_id, and width.

Referenced by FlutterEngineGetProcAddresses(), and FlutterEngineRun().

◆ FlutterEngineMarkExternalTextureFrameAvailable()

FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable ( FLUTTER_API_SYMBOL(FlutterEngine engine,
int64_t  texture_identifier 
)

Mark that a new texture frame is available for a given texture identifier.

See also
FlutterEngineRegisterExternalTexture()
FlutterEngineUnregisterExternalTexture()
Parameters
[in]engineA running engine instance.
[in]texture_identifierThe identifier of the texture whose frame has been updated.
Returns
The result of the call.

Definition at line 3195 of file embedder.cc.

3197 {
3198 if (engine == nullptr) {
3199 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3200 }
3201 if (texture_identifier == 0) {
3202 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid texture identifier.");
3203 }
3204 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3205 ->MarkTextureFrameAvailable(texture_identifier)) {
3206 return LOG_EMBEDDER_ERROR(
3208 "Could not mark the texture frame as being available.");
3209 }
3210 return kSuccess;
3211}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses().

◆ FlutterEngineNotifyDisplayUpdate()

FlutterEngineResult FlutterEngineNotifyDisplayUpdate ( FLUTTER_API_SYMBOL(FlutterEngine engine,
FlutterEngineDisplaysUpdateType  update_type,
const FlutterEngineDisplay displays,
size_t  display_count 
)

Posts updates corresponding to display changes to a running engine instance.

Parameters
[in]update_typeThe type of update pushed to the engine.
[in]displaysThe displays affected by this update.
[in]display_countSize of the displays array, must be at least 1.
Returns
the result of the call made to the engine.

Definition at line 3658 of file embedder.cc.

3662 {
3663 if (raw_engine == nullptr) {
3664 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3665 }
3666
3667 if (!ValidDisplayConfiguration(embedder_displays, display_count)) {
3668 return LOG_EMBEDDER_ERROR(
3670 "Invalid FlutterEngineDisplay configuration specified.");
3671 }
3672
3673 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3674
3675 switch (update_type) {
3677 std::vector<std::unique_ptr<flutter::Display>> displays;
3678 const auto* display = embedder_displays;
3679 for (size_t i = 0; i < display_count; i++) {
3680 displays.push_back(std::make_unique<flutter::Display>(
3681 SAFE_ACCESS(display, display_id, i), //
3682 SAFE_ACCESS(display, refresh_rate, 0), //
3683 SAFE_ACCESS(display, width, 0), //
3684 SAFE_ACCESS(display, height, 0), //
3685 SAFE_ACCESS(display, device_pixel_ratio, 1)));
3686 display = reinterpret_cast<const FlutterEngineDisplay*>(
3687 reinterpret_cast<const uint8_t*>(display) + display->struct_size);
3688 }
3689 engine->GetShell().OnDisplayUpdates(std::move(displays));
3690 return kSuccess;
3691 }
3692 default:
3693 return LOG_EMBEDDER_ERROR(
3695 "Invalid FlutterEngineDisplaysUpdateType type specified.");
3696 }
3697}

References displays, engine, height, i, kFlutterEngineDisplaysUpdateTypeStartup, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, SAFE_ACCESS, and width.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineNotifyLowMemoryWarning()

FlutterEngineResult FlutterEngineNotifyLowMemoryWarning ( FLUTTER_API_SYMBOL(FlutterEngine engine)

Posts a low memory notification to a running engine instance. The engine will do its best to release non-critical resources in response. It is not guaranteed that the resource would have been collected by the time this call returns however. The notification is posted to engine subsystems that may be operating on other threads.

Flutter applications can respond to these notifications by setting WidgetsBindingObserver.didHaveMemoryPressure observers.

Parameters
[in]engineA running engine instance.
Returns
If the low memory notification was sent to the running engine instance.

Definition at line 3597 of file embedder.cc.

3598 {
3599 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3600 if (engine == nullptr || !engine->IsValid()) {
3601 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine was invalid.");
3602 }
3603
3604 engine->GetShell().NotifyLowMemoryWarning();
3605
3606 rapidjson::Document document;
3607 auto& allocator = document.GetAllocator();
3608
3609 document.SetObject();
3610 document.AddMember("type", "memoryPressure", allocator);
3611
3612 return DispatchJSONPlatformMessage(raw_engine, document, "flutter/system")
3613 ? kSuccess
3616 "Could not dispatch the low memory notification message.");
3617}

References allocator, DispatchJSONPlatformMessage(), engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEngineOnVsync()

FlutterEngineResult FlutterEngineOnVsync ( FLUTTER_API_SYMBOL(FlutterEngine engine,
intptr_t  baton,
uint64_t  frame_start_time_nanos,
uint64_t  frame_target_time_nanos 
)

Notify the engine that a vsync event occurred. A baton passed to the platform via the vsync callback must be returned. This call must be made on the thread on which the call to FlutterEngineRun was made.

See also
FlutterEngineGetCurrentTime()
Attention
That frame timepoints are in nanoseconds.
The system monotonic clock is used as the timebase.
Parameters
[in]engine.A running engine instance.
[in]batonThe baton supplied by the engine.
[in]frame_start_time_nanosThe point at which the vsync event occurred or will occur. If the time point is in the future, the engine will wait till that point to begin its frame workload.
[in]frame_target_time_nanosThe point at which the embedder anticipates the next vsync to occur. This is a hint the engine uses to schedule Dart VM garbage collection in periods in which the various threads are most likely to be idle. For example, for a 60Hz display, embedders should add 16.6 * 1e6 to the frame time field.
Returns
The result of the call.

Definition at line 3274 of file embedder.cc.

3278 {
3279 if (engine == nullptr) {
3280 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3281 }
3282
3283 TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
3284
3285 auto start_time = fml::TimePoint::FromEpochDelta(
3286 fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
3287
3288 auto target_time = fml::TimePoint::FromEpochDelta(
3289 fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
3290
3291 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
3292 baton, start_time, target_time)) {
3293 return LOG_EMBEDDER_ERROR(
3295 "Could not notify the running engine instance of a Vsync event.");
3296 }
3297
3298 return kSuccess;
3299}

References engine, fml::TimePoint::FromEpochDelta(), fml::TimeDelta::FromNanoseconds(), kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and TRACE_EVENT0.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEnginePostCallbackOnAllNativeThreads()

FlutterEngineResult FlutterEnginePostCallbackOnAllNativeThreads ( FLUTTER_API_SYMBOL(FlutterEngine engine,
FlutterNativeThreadCallback  callback,
void *  user_data 
)

Schedule a callback to be run on all engine managed threads. The engine will attempt to service this callback the next time the message loop for each managed thread is idle. Since the engine manages the entire lifecycle of multiple threads, there is no opportunity for the embedders to finely tune the priorities of threads directly, or, perform other thread specific configuration (for example, setting thread names for tracing). This callback gives embedders a chance to affect such tuning.

Attention
This call is expensive and must be made as few times as possible. The callback must also return immediately as not doing so may risk performance issues (especially for callbacks of type kFlutterNativeThreadTypeUI and kFlutterNativeThreadTypeRender).
Some callbacks (especially the ones of type kFlutterNativeThreadTypeWorker) may be called after the FlutterEngine instance has shut down. Embedders must be careful in handling the lifecycle of objects associated with the user data baton.
In case there are multiple running Flutter engine instances, their workers are shared.
Parameters
[in]engineA running engine instance.
[in]callbackThe callback that will get called multiple times on each engine managed thread.
[in]user_dataA baton passed by the engine to the callback. This baton is not interpreted by the engine in any way.
Returns
Returns if the callback was successfully posted to all threads.

Definition at line 3619 of file embedder.cc.

3622 {
3623 if (engine == nullptr) {
3624 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3625 }
3626
3627 if (callback == nullptr) {
3629 "Invalid native thread callback.");
3630 }
3631
3632 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3633 ->PostTaskOnEngineManagedNativeThreads(
3636 })
3637 ? kSuccess
3639 "Internal error while attempting to post "
3640 "tasks to all threads.");
3641}

References callback, engine, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, type, and user_data.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEnginePostDartObject()

FlutterEngineResult FlutterEnginePostDartObject ( FLUTTER_API_SYMBOL(FlutterEngine engine,
FlutterEngineDartPort  port,
const FlutterEngineDartObject object 
)

Posts a Dart object to specified send port. The corresponding receive port for send port can be in any isolate running in the VM. This isolate can also be the root isolate for an unrelated engine. The engine parameter is necessary only to ensure the call is not made when no engine (and hence no VM) is running.

Unlike the platform messages mechanism, there are no threading restrictions when using this API. Message can be posted on any thread and they will be made available to isolate on which the corresponding send port is listening.

However, it is the embedders responsibility to ensure that the call is not made during an ongoing call the FlutterEngineDeinitialize or FlutterEngineShutdown on another thread.

Parameters
[in]engineA running engine instance.
[in]portThe send port to send the object to.
[in]objectThe object to send to the isolate with the corresponding receive port.
Returns
If the message was posted to the send port.

Definition at line 3473 of file embedder.cc.

3476 {
3477 if (engine == nullptr) {
3478 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3479 }
3480
3481 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->IsValid()) {
3482 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine not running.");
3483 }
3484
3485 if (port == ILLEGAL_PORT) {
3487 "Attempted to post to an illegal port.");
3488 }
3489
3490 if (object == nullptr) {
3492 "Invalid Dart object to post.");
3493 }
3494
3495 Dart_CObject dart_object = {};
3496 fml::ScopedCleanupClosure typed_data_finalizer;
3497
3498 switch (object->type) {
3500 dart_object.type = Dart_CObject_kNull;
3501 break;
3503 dart_object.type = Dart_CObject_kBool;
3504 dart_object.value.as_bool = object->bool_value;
3505 break;
3507 dart_object.type = Dart_CObject_kInt32;
3508 dart_object.value.as_int32 = object->int32_value;
3509 break;
3511 dart_object.type = Dart_CObject_kInt64;
3512 dart_object.value.as_int64 = object->int64_value;
3513 break;
3515 dart_object.type = Dart_CObject_kDouble;
3516 dart_object.value.as_double = object->double_value;
3517 break;
3519 if (object->string_value == nullptr) {
3521 "kFlutterEngineDartObjectTypeString must be "
3522 "a null terminated string but was null.");
3523 }
3524 dart_object.type = Dart_CObject_kString;
3525 dart_object.value.as_string = const_cast<char*>(object->string_value);
3526 break;
3528 auto* buffer = SAFE_ACCESS(object->buffer_value, buffer, nullptr);
3529 if (buffer == nullptr) {
3531 "kFlutterEngineDartObjectTypeBuffer must "
3532 "specify a buffer but found nullptr.");
3533 }
3534 auto buffer_size = SAFE_ACCESS(object->buffer_value, buffer_size, 0);
3535 auto callback =
3536 SAFE_ACCESS(object->buffer_value, buffer_collect_callback, nullptr);
3537 auto user_data = SAFE_ACCESS(object->buffer_value, user_data, nullptr);
3538
3539 // The user has provided a callback, let them manage the lifecycle of
3540 // the underlying data. If not, copy it out from the provided buffer.
3541
3542 if (callback == nullptr) {
3543 dart_object.type = Dart_CObject_kTypedData;
3544 dart_object.value.as_typed_data.type = Dart_TypedData_kUint8;
3545 dart_object.value.as_typed_data.length = buffer_size;
3546 dart_object.value.as_typed_data.values = buffer;
3547 } else {
3548 struct ExternalTypedDataPeer {
3549 void* user_data = nullptr;
3550 VoidCallback trampoline = nullptr;
3551 };
3552 auto peer = new ExternalTypedDataPeer();
3553 peer->user_data = user_data;
3554 peer->trampoline = callback;
3555 // This finalizer is set so that in case of failure of the
3556 // Dart_PostCObject below, we collect the peer. The embedder is still
3557 // responsible for collecting the buffer in case of non-kSuccess
3558 // returns from this method. This finalizer must be released in case
3559 // of kSuccess returns from this method.
3560 typed_data_finalizer.SetClosure([peer]() {
3561 // This is the tiny object we use as the peer to the Dart call so
3562 // that we can attach the a trampoline to the embedder supplied
3563 // callback. In case of error, we need to collect this object lest
3564 // we introduce a tiny leak.
3565 delete peer;
3566 });
3567 dart_object.type = Dart_CObject_kExternalTypedData;
3568 dart_object.value.as_external_typed_data.type = Dart_TypedData_kUint8;
3569 dart_object.value.as_external_typed_data.length = buffer_size;
3570 dart_object.value.as_external_typed_data.data = buffer;
3571 dart_object.value.as_external_typed_data.peer = peer;
3572 dart_object.value.as_external_typed_data.callback =
3573 +[](void* unused_isolate_callback_data, void* peer) {
3574 auto typed_peer = reinterpret_cast<ExternalTypedDataPeer*>(peer);
3575 typed_peer->trampoline(typed_peer->user_data);
3576 delete typed_peer;
3577 };
3578 }
3579 } break;
3580 default:
3581 return LOG_EMBEDDER_ERROR(
3583 "Invalid FlutterEngineDartObjectType type specified.");
3584 }
3585
3586 if (!Dart_PostCObject(port, &dart_object)) {
3588 "Could not post the object to the Dart VM.");
3589 }
3590
3591 // On a successful call, the VM takes ownership of and is responsible for
3592 // invoking the finalizer.
3593 typed_data_finalizer.Release();
3594 return kSuccess;
3595}

References FlutterEngineDartObject::buffer_value, callback, engine, kFlutterEngineDartObjectTypeBool, kFlutterEngineDartObjectTypeBuffer, kFlutterEngineDartObjectTypeDouble, kFlutterEngineDartObjectTypeInt32, kFlutterEngineDartObjectTypeInt64, kFlutterEngineDartObjectTypeNull, kFlutterEngineDartObjectTypeString, kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, fml::ScopedCleanupClosure::Release(), SAFE_ACCESS, fml::ScopedCleanupClosure::SetClosure(), FlutterEngineDartObject::string_value, FlutterEngineDartObject::type, and user_data.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEnginePostRenderThreadTask()

FlutterEngineResult FlutterEnginePostRenderThreadTask ( FLUTTER_API_SYMBOL(FlutterEngine engine,
VoidCallback  callback,
void *  callback_data 
)

Posts a task onto the Flutter render thread. Typically, this may be called from any thread as long as a FlutterEngineShutdown on the specific engine has not already been initiated.

Parameters
[in]engineA running engine instance.
[in]callbackThe callback to execute on the render thread.
callback_dataThe callback context.
Returns
The result of the call.

Definition at line 3332 of file embedder.cc.

3335 {
3336 if (engine == nullptr) {
3337 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3338 }
3339
3340 if (callback == nullptr) {
3342 "Render thread callback was null.");
3343 }
3344
3345 auto task = [callback, baton]() { callback(baton); };
3346
3347 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3348 ->PostRenderThreadTask(task)
3349 ? kSuccess
3351 "Could not post the render thread task.");
3352}

References callback, engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses().

◆ FlutterEngineRegisterExternalTexture()

FlutterEngineResult FlutterEngineRegisterExternalTexture ( FLUTTER_API_SYMBOL(FlutterEngine engine,
int64_t  texture_identifier 
)

Register an external texture with a unique (per engine) identifier. Only rendering backends that support external textures accept external texture registrations. After the external texture is registered, the application can mark that a frame is available by calling FlutterEngineMarkExternalTextureFrameAvailable.

See also
FlutterEngineUnregisterExternalTexture()
FlutterEngineMarkExternalTextureFrameAvailable()
Parameters
[in]engineA running engine instance.
[in]texture_identifierThe identifier of the texture to register with the engine. The embedder may supply new frames to this texture using the same identifier.
Returns
The result of the call.

Definition at line 3155 of file embedder.cc.

3157 {
3158 if (engine == nullptr) {
3159 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3160 }
3161
3162 if (texture_identifier == 0) {
3164 "Texture identifier was invalid.");
3165 }
3166 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
3167 texture_identifier)) {
3169 "Could not register the specified texture.");
3170 }
3171 return kSuccess;
3172}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEngineReloadSystemFonts()

FlutterEngineResult FlutterEngineReloadSystemFonts ( FLUTTER_API_SYMBOL(FlutterEngine engine)

Reloads the system fonts in engine.

Parameters
[in]engine.A running engine instance.
Returns
The result of the call.

Definition at line 3301 of file embedder.cc.

3302 {
3303 if (engine == nullptr) {
3304 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3305 }
3306
3307 TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
3308
3309 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3310 ->ReloadSystemFonts()) {
3312 "Could not reload system fonts.");
3313 }
3314
3315 return kSuccess;
3316}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and TRACE_EVENT0.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEngineRemoveView()

FLUTTER_EXPORT FlutterEngineResult FlutterEngineRemoveView ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterRemoveViewInfo info 
)

Removes a view.

        This is an asynchronous operation. The view's resources must not
        be cleaned up until |info.remove_view_callback| is invoked with
        a |removed| value of true.

        The callback is invoked on a thread managed by the engine. The
        embedder should re-thread if needed.

        Attempting to remove the implicit view will fail and will return
        kInvalidArguments. Attempting to remove a view with a
        non-existent view ID will fail, and |info.remove_view_callback|
        will be invoked with a |removed| value of false.
Parameters
[in]engineA running engine instance.
[in]infoThe remove view arguments. This can be deallocated once |FlutterEngineRemoveView| returns, before |remove_view_callback| is invoked.
Returns
The result of starting the asynchronous operation. If kSuccess, the |remove_view_callback| will be invoked.

Definition at line 2601 of file embedder.cc.

2603 {
2604 if (!engine) {
2605 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2606 }
2607 if (!info || !info->remove_view_callback) {
2609 "Remove view info handle was invalid.");
2610 }
2611
2612 if (info->view_id == kFlutterImplicitViewId) {
2613 return LOG_EMBEDDER_ERROR(
2615 "Remove view info was invalid. The implicit view cannot be removed.");
2616 }
2617
2618 // TODO(loicsharma): Return an error if the engine was initialized with
2619 // callbacks that are incompatible with multiple views.
2620 // https://github.com/flutter/flutter/issues/144806
2621
2622 // The engine must be running to remove a view.
2623 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2624 if (!embedder_engine->IsValid()) {
2625 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2626 }
2627
2629 [c_callback = info->remove_view_callback,
2630 user_data = info->user_data](bool removed) {
2631 FlutterRemoveViewResult result = {};
2632 result.struct_size = sizeof(FlutterRemoveViewResult);
2633 result.removed = removed;
2634 result.user_data = user_data;
2635 c_callback(&result);
2636 };
2637
2638 embedder_engine->GetShell().GetPlatformView()->RemoveView(info->view_id,
2639 callback);
2640 return kSuccess;
2641}

References callback, engine, kFlutterImplicitViewId, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, FlutterRemoveViewInfo::remove_view_callback, FlutterRemoveViewResult::removed, FlutterRemoveViewResult::struct_size, user_data, FlutterRemoveViewResult::user_data, FlutterRemoveViewInfo::user_data, and FlutterRemoveViewInfo::view_id.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineRun()

FlutterEngineResult FlutterEngineRun ( size_t  version,
const FlutterRendererConfig config,
const FlutterProjectArgs args,
void *  user_data,
FLUTTER_API_SYMBOL(FlutterEngine) *  engine_out 
)

Initialize and run a Flutter engine instance and return a handle to it. This is a convenience method for the pair of calls to FlutterEngineInitialize and FlutterEngineRunInitialized.

Note
This method of running a Flutter engine works well except in cases where the embedder specifies custom task runners via FlutterProjectArgs::custom_task_runners. In such cases, the engine may need the embedder to post tasks back to it before FlutterEngineRun has returned. Embedders can only post tasks to the engine if they have a handle to the engine. In such cases, embedders are advised to get the engine handle by calling FlutterEngineInitialize. Then they can call FlutterEngineRunInitialized knowing that they will be able to service custom tasks on other threads with the engine handle.
Parameters
[in]versionThe Flutter embedder API version. Must be FLUTTER_ENGINE_VERSION.
[in]configThe renderer configuration.
[in]argsThe Flutter project arguments.
user_dataA user data baton passed back to embedders in callbacks.
[out]engine_outThe engine handle on successful engine creation.
Returns
The result of the call to run the Flutter engine.

Definition at line 2006 of file embedder.cc.

2011 {
2012 auto result =
2013 FlutterEngineInitialize(version, config, args, user_data, engine_out);
2014
2015 if (result != kSuccess) {
2016 return result;
2017 }
2018
2019 return FlutterEngineRunInitialized(*engine_out);
2020}

References args, FlutterEngineInitialize(), FlutterEngineRunInitialized(), kSuccess, and user_data.

Referenced by FlutterEngineGetProcAddresses(), main(), RunFlutter(), and RunFlutterEngine().

◆ FlutterEngineRunInitialized()

FlutterEngineResult FlutterEngineRunInitialized ( FLUTTER_API_SYMBOL(FlutterEngine engine)

Runs an initialized engine instance. An engine can be initialized via FlutterEngineInitialize. An initialized instance can only be run once. During and after this call, custom task runners supplied by the embedder are expected to start servicing tasks.

Parameters
[in]engineAn initialized engine instance that has not previously been run.
Returns
The result of the call to run the initialized Flutter engine instance.

Definition at line 2501 of file embedder.cc.

2502 {
2503 if (!engine) {
2504 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2505 }
2506
2507 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2508
2509 // The engine must not already be running. Initialize may only be called
2510 // once on an engine instance.
2511 if (embedder_engine->IsValid()) {
2512 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2513 }
2514
2515 // Step 1: Launch the shell.
2516 if (!embedder_engine->LaunchShell()) {
2518 "Could not launch the engine using supplied "
2519 "initialization arguments.");
2520 }
2521
2522 // Step 2: Tell the platform view to initialize itself.
2523 if (!embedder_engine->NotifyCreated()) {
2525 "Could not create platform view components.");
2526 }
2527
2528 // Step 3: Launch the root isolate.
2529 if (!embedder_engine->RunRootIsolate()) {
2530 return LOG_EMBEDDER_ERROR(
2532 "Could not run the root isolate of the Flutter application using the "
2533 "project arguments specified.");
2534 }
2535
2536 return kSuccess;
2537}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses(), FlutterEngineRun(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_P().

◆ FlutterEngineRunsAOTCompiledDartCode()

bool FlutterEngineRunsAOTCompiledDartCode ( void  )

Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading restrictions.

For embedder code that is configured for both AOT and JIT mode Dart execution based on the Flutter engine being linked to, this runtime check may be used to appropriately configure the FlutterProjectArgs. In JIT mode execution, the kernel snapshots must be present in the Flutter assets directory specified in the FlutterProjectArgs. For AOT execution, the fields vm_snapshot_data, vm_snapshot_instructions, isolate_snapshot_data and isolate_snapshot_instructions (along with their size fields) must be specified in FlutterProjectArgs.

Returns
True, if AOT Dart code is run. JIT otherwise.

Definition at line 3469 of file embedder.cc.

3469 {
3471}

References flutter::DartVM::IsRunningPrecompiledCode().

Referenced by FlutterEngineGetProcAddresses(), RunFlutterEngine(), and flutter::testing::TEST_F().

◆ FlutterEngineRunTask()

FlutterEngineResult FlutterEngineRunTask ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterTask task 
)

Inform the engine to run the specified task. This task has been given to the embedder via the FlutterTaskRunnerDescription.post_task_callback. This call must only be made at the target time specified in that callback. Running the task before that time is undefined behavior.

Parameters
[in]engineA running engine instance.
[in]taskthe task handle.
Returns
The result of the call.

Definition at line 3358 of file embedder.cc.

3360 {
3361 if (engine == nullptr) {
3362 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3363 }
3364
3366 reinterpret_cast<intptr_t>(task->runner))) {
3367 // This task came too late, the embedder has already been destroyed.
3368 // This is not an error, just ignore the task.
3369 return kSuccess;
3370 }
3371
3372 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
3373 ? kSuccess
3375 "Could not run the specified task.");
3376}

References engine, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, FlutterTask::runner, and flutter::EmbedderThreadHost::RunnerIsValid().

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_P().

◆ FlutterEngineScheduleFrame()

FlutterEngineResult FlutterEngineScheduleFrame ( FLUTTER_API_SYMBOL(FlutterEngine engine)

Schedule a new frame to redraw the content.

Parameters
[in]engineA running engine instance.
Returns
the result of the call made to the engine.

Definition at line 3699 of file embedder.cc.

3700 {
3701 if (engine == nullptr) {
3702 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3703 }
3704
3705 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->ScheduleFrame()
3706 ? kSuccess
3708 "Could not schedule frame.");
3709}

References engine, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEngineSendKeyEvent()

FlutterEngineResult FlutterEngineSendKeyEvent ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterKeyEvent event,
FlutterKeyEventCallback  callback,
void *  user_data 
)

Sends a key event to the engine. The framework will decide whether to handle this event in a synchronous fashion, although due to technical limitation, the result is always reported asynchronously. The callback is guaranteed to be called exactly once.

Parameters
[in]engineA running engine instance.
[in]eventThe event data to be sent. This function will no longer access event after returning.
[in]callbackThe callback invoked by the engine when the Flutter application has decided whether it handles this event. Accepts nullptr.
[in]user_dataThe context associated with the callback. The exact same value will used to invoke callback. Accepts nullptr.
Returns
The result of the call.

Definition at line 2966 of file embedder.cc.

2970 {
2971 if (engine == nullptr) {
2972 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2973 }
2974
2975 if (event == nullptr) {
2976 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid key event.");
2977 }
2978
2979 const char* character = SAFE_ACCESS(event, character, nullptr);
2980
2981 flutter::KeyData key_data;
2982 key_data.Clear();
2983 key_data.timestamp = static_cast<uint64_t>(SAFE_ACCESS(event, timestamp, 0));
2984 key_data.type = MapKeyEventType(
2986 key_data.physical = SAFE_ACCESS(event, physical, 0);
2987 key_data.logical = SAFE_ACCESS(event, logical, 0);
2988 key_data.synthesized = SAFE_ACCESS(event, synthesized, false);
2990 event, device_type,
2992
2993 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data, character);
2994
2995 struct MessageData {
2997 void* user_data;
2998 };
2999
3000 MessageData* message_data =
3001 new MessageData{.callback = callback, .user_data = user_data};
3002
3003 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
3005 engine, kFlutterKeyDataChannel, packet->data().data(),
3006 packet->data().size(),
3007 [](const uint8_t* data, size_t size, void* user_data) {
3008 auto message_data = std::unique_ptr<MessageData>(
3009 reinterpret_cast<MessageData*>(user_data));
3010 if (message_data->callback == nullptr) {
3011 return;
3012 }
3013 bool handled = false;
3014 if (size == 1) {
3015 handled = *data != 0;
3016 }
3017 message_data->callback(handled, message_data->user_data);
3018 },
3019 message_data);
3020}

References callback, character, flutter::KeyData::Clear(), flutter::KeyData::device_type, engine, InternalSendPlatformMessage(), kFlutterKeyDataChannel, kFlutterKeyEventDeviceTypeKeyboard, kFlutterKeyEventTypeUp, kInvalidArguments, LOG_EMBEDDER_ERROR, flutter::KeyData::logical, MapKeyEventDeviceType(), MapKeyEventType(), flutter::KeyData::physical, SAFE_ACCESS, flutter::KeyData::synthesized, flutter::KeyData::timestamp, type, flutter::KeyData::type, and user_data.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineSendPlatformMessage()

FlutterEngineResult FlutterEngineSendPlatformMessage ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterPlatformMessage flutter_message 
)

Definition at line 3022 of file embedder.cc.

3024 {
3025 if (engine == nullptr) {
3026 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3027 }
3028
3029 if (flutter_message == nullptr) {
3030 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid message argument.");
3031 }
3032
3033 if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
3034 return LOG_EMBEDDER_ERROR(
3035 kInvalidArguments, "Message argument did not specify a valid channel.");
3036 }
3037
3038 size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
3039 const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
3040
3041 if (message_size != 0 && message_data == nullptr) {
3042 return LOG_EMBEDDER_ERROR(
3044 "Message size was non-zero but the message data was nullptr.");
3045 }
3046
3047 const FlutterPlatformMessageResponseHandle* response_handle =
3048 SAFE_ACCESS(flutter_message, response_handle, nullptr);
3049
3051 if (response_handle && response_handle->message) {
3052 response = response_handle->message->response();
3053 }
3054
3055 std::unique_ptr<flutter::PlatformMessage> message;
3056 if (message_size == 0) {
3057 message = std::make_unique<flutter::PlatformMessage>(
3058 flutter_message->channel, response);
3059 } else {
3060 message = std::make_unique<flutter::PlatformMessage>(
3061 flutter_message->channel,
3062 fml::MallocMapping::Copy(message_data, message_size), response);
3063 }
3064
3065 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3066 ->SendPlatformMessage(std::move(message))
3067 ? kSuccess
3069 "Could not send a message to the running "
3070 "Flutter application.");
3071}

References FlutterPlatformMessage::channel, channel, fml::MallocMapping::Copy(), engine, kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, _FlutterPlatformMessageResponseHandle::message, message, and SAFE_ACCESS.

Referenced by FlutterDesktopMessengerSendWithReply(), FlutterEngineGetProcAddresses(), InternalSendPlatformMessage(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineSendPlatformMessageResponse()

FlutterEngineResult FlutterEngineSendPlatformMessageResponse ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterPlatformMessageResponseHandle handle,
const uint8_t *  data,
size_t  data_length 
)

Send a response from the native side to a platform message from the Dart Flutter application.

Parameters
[in]engineThe running engine instance.
[in]handleThe platform message response handle.
[in]dataThe data to associate with the platform message response.
[in]data_lengthThe length of the platform message response data.
Returns
The result of the call.

Definition at line 3123 of file embedder.cc.

3127 {
3128 if (data_length != 0 && data == nullptr) {
3129 return LOG_EMBEDDER_ERROR(
3131 "Data size was non zero but the pointer to the data was null.");
3132 }
3133
3134 auto response = handle->message->response();
3135
3136 if (response) {
3137 if (data_length == 0) {
3138 response->CompleteEmpty();
3139 } else {
3140 response->Complete(std::make_unique<fml::DataMapping>(
3141 std::vector<uint8_t>({data, data + data_length})));
3142 }
3143 }
3144
3145 delete handle;
3146
3147 return kSuccess;
3148}

References kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and _FlutterPlatformMessageResponseHandle::message.

Referenced by FlutterDesktopMessengerSendResponse(), FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineSendPointerEvent()

FlutterEngineResult FlutterEngineSendPointerEvent ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterPointerEvent pointers,
size_t  events_count 
)

Definition at line 2811 of file embedder.cc.

2814 {
2815 if (engine == nullptr) {
2816 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2817 }
2818
2819 if (pointers == nullptr || events_count == 0) {
2820 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid pointer events.");
2821 }
2822
2823 auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
2824
2825 const FlutterPointerEvent* current = pointers;
2826
2827 for (size_t i = 0; i < events_count; ++i) {
2828 flutter::PointerData pointer_data;
2829 pointer_data.Clear();
2830 // this is currely in use only on android embedding.
2831 pointer_data.embedder_id = 0;
2832 pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
2833 pointer_data.change = ToPointerDataChange(
2834 SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
2835 pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
2836 pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
2837 // Delta will be generated in pointer_data_packet_converter.cc.
2838 pointer_data.physical_delta_x = 0.0;
2839 pointer_data.physical_delta_y = 0.0;
2840 pointer_data.device = SAFE_ACCESS(current, device, 0);
2841 // Pointer identifier will be generated in
2842 // pointer_data_packet_converter.cc.
2843 pointer_data.pointer_identifier = 0;
2844 pointer_data.signal_kind = ToPointerDataSignalKind(
2845 SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
2846 pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
2847 pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
2848 FlutterPointerDeviceKind device_kind =
2849 SAFE_ACCESS(current, device_kind, kFlutterPointerDeviceKindMouse);
2850 // For backwards compatibility with embedders written before the device
2851 // kind and buttons were exposed, if the device kind is not set treat it
2852 // as a mouse, with a synthesized primary button state based on the phase.
2853 if (device_kind == 0) {
2855 pointer_data.buttons =
2857
2858 } else {
2859 pointer_data.kind = ToPointerDataKind(device_kind);
2860 if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
2861 // For touch events, set the button internally rather than requiring
2862 // it at the API level, since it's a confusing construction to expose.
2863 if (pointer_data.change == flutter::PointerData::Change::kDown ||
2866 }
2867 } else {
2868 // Buttons use the same mask values, so pass them through directly.
2869 pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
2870 }
2871 }
2872 pointer_data.pan_x = SAFE_ACCESS(current, pan_x, 0.0);
2873 pointer_data.pan_y = SAFE_ACCESS(current, pan_y, 0.0);
2874 // Delta will be generated in pointer_data_packet_converter.cc.
2875 pointer_data.pan_delta_x = 0.0;
2876 pointer_data.pan_delta_y = 0.0;
2877 pointer_data.scale = SAFE_ACCESS(current, scale, 0.0);
2878 pointer_data.rotation = SAFE_ACCESS(current, rotation, 0.0);
2879 pointer_data.pressure = SAFE_ACCESS(current, pressure, 0.0);
2880 pointer_data.pressure_min = SAFE_ACCESS(current, pressure_min, 0.0);
2881 pointer_data.pressure_max = SAFE_ACCESS(current, pressure_max, 0.0);
2882 pointer_data.view_id =
2884 packet->SetPointerData(i, pointer_data);
2885 current = reinterpret_cast<const FlutterPointerEvent*>(
2886 reinterpret_cast<const uint8_t*>(current) + current->struct_size);
2887 }
2888
2889 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2890 ->DispatchPointerDataPacket(std::move(packet))
2891 ? kSuccess
2893 "Could not dispatch pointer events to the "
2894 "running Flutter application.");
2895}

References flutter::PointerData::buttons, flutter::PointerData::change, flutter::PointerData::Clear(), device, flutter::PointerData::device, flutter::PointerData::embedder_id, engine, i, kCancel, flutter::PointerData::kDown, kFlutterImplicitViewId, kFlutterPointerDeviceKindMouse, kFlutterPointerSignalKindNone, flutter::PointerData::kind, kInternalInconsistency, kInvalidArguments, flutter::PointerData::kMouse, flutter::PointerData::kMove, flutter::kPointerButtonTouchContact, kSuccess, flutter::PointerData::kTouch, LOG_EMBEDDER_ERROR, flutter::PointerData::pan_delta_x, flutter::PointerData::pan_delta_y, flutter::PointerData::pan_x, flutter::PointerData::pan_y, flutter::PointerData::physical_delta_x, flutter::PointerData::physical_delta_y, flutter::PointerData::physical_x, flutter::PointerData::physical_y, flutter::PointerData::pointer_identifier, PointerDataButtonsForLegacyEvent(), flutter::PointerData::pressure, flutter::PointerData::pressure_max, flutter::PointerData::pressure_min, flutter::PointerData::rotation, SAFE_ACCESS, flutter::PointerData::scale, flutter::PointerData::scroll_delta_x, flutter::PointerData::scroll_delta_y, flutter::PointerData::signal_kind, FlutterPointerEvent::struct_size, flutter::PointerData::time_stamp, ToPointerDataChange(), ToPointerDataKind(), ToPointerDataSignalKind(), flutter::PointerData::view_id, view_id, x, and y.

Referenced by FlutterEngineGetProcAddresses(), GLFWcursorPositionCallbackAtPhase(), SendPointerEventWithData(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineSendSemanticsAction()

FlutterEngineResult FlutterEngineSendSemanticsAction ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterSendSemanticsActionInfo info 
)

Dispatch a semantics action to the specified semantics node within a specific view.

Parameters
[in]engineA running engine instance.
[in]infoThe dispatch semantics on view arguments. This can be deallocated once |FlutterEngineSendSemanticsAction| returns.
Returns
The result of the call.

Definition at line 3257 of file embedder.cc.

3259 {
3260 if (engine == nullptr) {
3261 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3262 }
3263 auto engine_action = static_cast<flutter::SemanticsAction>(info->action);
3264 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3266 info->view_id, info->node_id, engine_action,
3267 fml::MallocMapping::Copy(info->data, info->data_length))) {
3269 "Could not dispatch semantics action.");
3270 }
3271 return kSuccess;
3272}

References FlutterSendSemanticsActionInfo::action, fml::MallocMapping::Copy(), FlutterSendSemanticsActionInfo::data, FlutterSendSemanticsActionInfo::data_length, flutter::EmbedderEngine::DispatchSemanticsAction(), engine, kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, FlutterSendSemanticsActionInfo::node_id, and FlutterSendSemanticsActionInfo::view_id.

Referenced by FlutterEngineDispatchSemanticsAction(), and FlutterEngineGetProcAddresses().

◆ FlutterEngineSendViewFocusEvent()

FlutterEngineResult FlutterEngineSendViewFocusEvent ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterViewFocusEvent event 
)

Notifies the engine that platform view focus state has changed.

Parameters
[in]engineA running engine instance
[in]eventThe focus event data describing the change.

Definition at line 2643 of file embedder.cc.

2645 {
2646 if (!engine) {
2647 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2648 }
2649 if (!event) {
2651 "View focus event must not be null.");
2652 }
2653 // The engine must be running to focus a view.
2654 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2655 if (!embedder_engine->IsValid()) {
2656 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2657 }
2658
2659 if (!STRUCT_HAS_MEMBER(event, direction)) {
2661 "The event struct has invalid size.");
2662 }
2663
2664 flutter::ViewFocusEvent flutter_event(
2665 event->view_id, //
2666 static_cast<flutter::ViewFocusState>(event->state),
2667 static_cast<flutter::ViewFocusDirection>(event->direction));
2668
2669 embedder_engine->GetShell().GetPlatformView()->SendViewFocusEvent(
2670 flutter_event);
2671
2672 return kSuccess;
2673}

References FlutterViewFocusEvent::direction, engine, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, FlutterViewFocusEvent::state, STRUCT_HAS_MEMBER, and FlutterViewFocusEvent::view_id.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEngineSendWindowMetricsEvent()

FlutterEngineResult FlutterEngineSendWindowMetricsEvent ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterWindowMetricsEvent flutter_metrics 
)

Definition at line 2700 of file embedder.cc.

2702 {
2703 if (engine == nullptr || flutter_metrics == nullptr) {
2704 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2705 }
2707 SAFE_ACCESS(flutter_metrics, view_id, kFlutterImplicitViewId);
2708
2709 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2710 MakeViewportMetricsFromWindowMetrics(flutter_metrics);
2711 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2712 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2713 }
2714
2715 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2716
2717 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
2718 view_id, metrics)
2719 ? kSuccess
2721 "Viewport metrics were invalid.");
2722}

References engine, error, kFlutterImplicitViewId, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, MakeViewportMetricsFromWindowMetrics(), SAFE_ACCESS, and view_id.

Referenced by flutter::testing::expectSoftwareRenderingOutputMatches(), FlutterEngineGetProcAddresses(), GLFWframebufferSizeCallback(), GLFWwindowSizeCallback(), SendWindowMetrics(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_P(), flutter::testing::TEST_P(), flutter::testing::TEST_P(), flutter::testing::TEST_P(), flutter::testing::TEST_P(), and flutter::testing::TEST_P().

◆ FlutterEngineSetNextFrameCallback()

FlutterEngineResult FlutterEngineSetNextFrameCallback ( FLUTTER_API_SYMBOL(FlutterEngine engine,
VoidCallback  callback,
void *  user_data 
)

Schedule a callback to be called after the next frame is drawn. This must be called from the platform thread. The callback is executed only once from the raster thread; embedders must re-thread if necessary. Performing blocking calls in this callback may introduce application jank.

Parameters
[in]engineA running engine instance.
[in]callbackThe callback to execute.
[in]user_dataA baton passed by the engine to the callback. This baton is not interpreted by the engine in any way.
Returns
The result of the call.

Definition at line 3711 of file embedder.cc.

3714 {
3715 if (engine == nullptr) {
3716 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3717 }
3718
3719 if (callback == nullptr) {
3721 "Next frame callback was null.");
3722 }
3723
3724 flutter::EmbedderEngine* embedder_engine =
3725 reinterpret_cast<flutter::EmbedderEngine*>(engine);
3726
3727 fml::WeakPtr<flutter::PlatformView> weak_platform_view =
3728 embedder_engine->GetShell().GetPlatformView();
3729
3730 if (!weak_platform_view) {
3732 "Platform view unavailable.");
3733 }
3734
3735 weak_platform_view->SetNextFrameCallback(
3737
3738 return kSuccess;
3739}

References callback, engine, flutter::Shell::GetPlatformView(), flutter::EmbedderEngine::GetShell(), kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and user_data.

Referenced by FlutterEngineGetProcAddresses(), and flutter::testing::TEST_F().

◆ FlutterEngineShutdown()

FlutterEngineResult FlutterEngineShutdown ( FLUTTER_API_SYMBOL(FlutterEngine engine)

Shuts down a Flutter engine instance. The engine handle is no longer valid for any calls in the embedder API after this point. Making additional calls with this handle is undefined behavior.

Note
This de-initializes the Flutter engine instance (via an implicit call to FlutterEngineDeinitialize) if necessary.
Parameters
[in]engineThe Flutter engine instance to collect.
Returns
The result of the call to shutdown the Flutter engine instance.

Definition at line 2689 of file embedder.cc.

2690 {
2691 auto result = FlutterEngineDeinitialize(engine);
2692 if (result != kSuccess) {
2693 return result;
2694 }
2695 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2696 delete embedder_engine;
2697 return kSuccess;
2698}

References engine, FlutterEngineDeinitialize(), and kSuccess.

Referenced by FlutterDesktopDestroyWindow(), FlutterDesktopShutDownEngine(), FlutterEngineGetProcAddresses(), flutter::testing::UniqueEngineTraits::Free(), main(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineTraceEventDurationBegin()

void FlutterEngineTraceEventDurationBegin ( const char *  name)

A profiling utility. Logs a trace duration begin event to the timeline. If the timeline is unavailable or disabled, this has no effect. Must be balanced with an duration end event (via FlutterEngineTraceEventDurationEnd) with the same name on the same thread. Can be called on any thread. Strings passed into the function will NOT be copied when added to the timeline. Only string literals may be passed in.

Parameters
[in]nameThe name of the trace event.

Definition at line 3318 of file embedder.cc.

3318 {
3319 fml::tracing::TraceEvent0("flutter", name, /*flow_id_count=*/0,
3320 /*flow_ids=*/nullptr);
3321}

References name, and fml::tracing::TraceEvent0().

Referenced by FlutterEngineGetProcAddresses().

◆ FlutterEngineTraceEventDurationEnd()

void FlutterEngineTraceEventDurationEnd ( const char *  name)

A profiling utility. Logs a trace duration end event to the timeline. If the timeline is unavailable or disabled, this has no effect. This call must be preceded by a trace duration begin call (via FlutterEngineTraceEventDurationBegin) with the same name on the same thread. Can be called on any thread. Strings passed into the function will NOT be copied when added to the timeline. Only string literals may be passed in.

Parameters
[in]nameThe name of the trace event.

Definition at line 3323 of file embedder.cc.

3323 {
3325}

References name, and fml::tracing::TraceEventEnd().

Referenced by FlutterEngineGetProcAddresses().

◆ FlutterEngineTraceEventInstant()

void FlutterEngineTraceEventInstant ( const char *  name)

A profiling utility. Logs a trace duration instant event to the timeline. If the timeline is unavailable or disabled, this has no effect. Can be called on any thread. Strings passed into the function will NOT be copied when added to the timeline. Only string literals may be passed in.

Parameters
[in]nameThe name of the trace event.

Definition at line 3327 of file embedder.cc.

3327 {
3328 fml::tracing::TraceEventInstant0("flutter", name, /*flow_id_count=*/0,
3329 /*flow_ids=*/nullptr);
3330}

References name, and fml::tracing::TraceEventInstant0().

Referenced by FlutterEngineGetProcAddresses().

◆ FlutterEngineUnregisterExternalTexture()

FlutterEngineResult FlutterEngineUnregisterExternalTexture ( FLUTTER_API_SYMBOL(FlutterEngine engine,
int64_t  texture_identifier 
)

Unregister a previous texture registration.

See also
FlutterEngineRegisterExternalTexture()
FlutterEngineMarkExternalTextureFrameAvailable()
Parameters
[in]engineA running engine instance.
[in]texture_identifierThe identifier of the texture for which new frame will not be available.
Returns
The result of the call.

Definition at line 3174 of file embedder.cc.

3176 {
3177 if (engine == nullptr) {
3178 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3179 }
3180
3181 if (texture_identifier == 0) {
3183 "Texture identifier was invalid.");
3184 }
3185
3186 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
3187 texture_identifier)) {
3189 "Could not un-register the specified texture.");
3190 }
3191
3192 return kSuccess;
3193}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses().

◆ FlutterEngineUpdateAccessibilityFeatures()

FlutterEngineResult FlutterEngineUpdateAccessibilityFeatures ( FLUTTER_API_SYMBOL(FlutterEngine engine,
FlutterAccessibilityFeature  features 
)

Sets additional accessibility features.

Parameters
[in]engineA running engine instance
[in]featuresThe accessibility features to set.
Returns
The result of the call.

Definition at line 3227 of file embedder.cc.

3229 {
3230 if (engine == nullptr) {
3231 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3232 }
3233 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3234 ->SetAccessibilityFeatures(flags)) {
3236 "Could not update accessibility features.");
3237 }
3238 return kSuccess;
3239}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterEngineUpdateLocales()

FlutterEngineResult FlutterEngineUpdateLocales ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const FlutterLocale **  locales,
size_t  locales_count 
)

Notify a running engine instance that the locale has been updated. The preferred locale must be the first item in the list of locales supplied. The other entries will be used as a fallback.

Parameters
[in]engineA running engine instance.
[in]localesThe updated locales in the order of preference.
[in]locales_countThe count of locales supplied.
Returns
Whether the locale updates were applied.

Definition at line 3410 of file embedder.cc.

3413 {
3414 if (engine == nullptr) {
3415 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3416 }
3417
3418 if (locales_count == 0) {
3419 return kSuccess;
3420 }
3421
3422 if (locales == nullptr) {
3423 return LOG_EMBEDDER_ERROR(kInvalidArguments, "No locales were specified.");
3424 }
3425
3426 rapidjson::Document document;
3427 auto& allocator = document.GetAllocator();
3428
3429 document.SetObject();
3430 document.AddMember("method", "setLocale", allocator);
3431
3432 rapidjson::Value args(rapidjson::kArrayType);
3433 args.Reserve(locales_count * 4, allocator);
3434 for (size_t i = 0; i < locales_count; ++i) {
3435 const FlutterLocale* locale = locales[i];
3436 const char* language_code_str = SAFE_ACCESS(locale, language_code, nullptr);
3437 if (language_code_str == nullptr || ::strlen(language_code_str) == 0) {
3438 return LOG_EMBEDDER_ERROR(
3440 "Language code is required but not present in FlutterLocale.");
3441 }
3442
3443 const char* country_code_str = SAFE_ACCESS(locale, country_code, "");
3444 const char* script_code_str = SAFE_ACCESS(locale, script_code, "");
3445 const char* variant_code_str = SAFE_ACCESS(locale, variant_code, "");
3446
3447 rapidjson::Value language_code, country_code, script_code, variant_code;
3448
3449 language_code.SetString(language_code_str, allocator);
3450 country_code.SetString(country_code_str ? country_code_str : "", allocator);
3451 script_code.SetString(script_code_str ? script_code_str : "", allocator);
3452 variant_code.SetString(variant_code_str ? variant_code_str : "", allocator);
3453
3454 // Required.
3455 args.PushBack(language_code, allocator);
3456 args.PushBack(country_code, allocator);
3457 args.PushBack(script_code, allocator);
3458 args.PushBack(variant_code, allocator);
3459 }
3460 document.AddMember("args", args, allocator);
3461
3462 return DispatchJSONPlatformMessage(engine, document, "flutter/localization")
3463 ? kSuccess
3465 "Could not send message to update locale of "
3466 "a running Flutter application.");
3467}

References allocator, args, DispatchJSONPlatformMessage(), engine, i, kInternalInconsistency, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and SAFE_ACCESS.

Referenced by FlutterEngineGetProcAddresses(), SetUpLocales(), and flutter::testing::TEST_F().

◆ FlutterEngineUpdateSemanticsEnabled()

FlutterEngineResult FlutterEngineUpdateSemanticsEnabled ( FLUTTER_API_SYMBOL(FlutterEngine engine,
bool  enabled 
)

Enable or disable accessibility semantics.

Parameters
[in]engineA running engine instance.
[in]enabledWhen enabled, changes to the semantic contents of the window are sent via the FlutterUpdateSemanticsCallback2 registered to update_semantics_callback2 in FlutterProjectArgs.
Returns
The result of the call.

Definition at line 3213 of file embedder.cc.

3215 {
3216 if (engine == nullptr) {
3217 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3218 }
3219 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetSemanticsEnabled(
3220 enabled)) {
3222 "Could not update semantics state.");
3223 }
3224 return kSuccess;
3225}

References engine, kInternalInconsistency, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterEngineGetProcAddresses(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterPlatformMessageCreateResponseHandle()

FlutterEngineResult FlutterPlatformMessageCreateResponseHandle ( FLUTTER_API_SYMBOL(FlutterEngine engine,
FlutterDataCallback  data_callback,
void *  user_data,
FlutterPlatformMessageResponseHandle **  response_out 
)

Creates a platform message response handle that allows the embedder to set a native callback for a response to a message. This handle may be set on the response_handle field of any FlutterPlatformMessage sent to the engine.

The handle must be collected via a call to FlutterPlatformMessageReleaseResponseHandle. This may be done immediately after a call to FlutterEngineSendPlatformMessage with a platform message whose response handle contains the handle created using this call. In case a handle is created but never sent in a message, the release call must still be made. Not calling release on the handle results in a small memory leak.

The user data baton passed to the data callback is the one specified in this call as the third argument.

See also
FlutterPlatformMessageReleaseResponseHandle()
Parameters
[in]engineA running engine instance.
[in]data_callbackThe callback invoked by the engine when the Flutter application send a response on the handle.
[in]user_dataThe user data associated with the data callback.
[out]response_outThe response handle created when this call is successful.
Returns
The result of the call.

Definition at line 3073 of file embedder.cc.

3077 {
3078 if (engine == nullptr) {
3079 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3080 }
3081
3082 if (data_callback == nullptr || response_out == nullptr) {
3083 return LOG_EMBEDDER_ERROR(
3084 kInvalidArguments, "Data callback or the response handle was invalid.");
3085 }
3086
3088 [user_data, data_callback](const uint8_t* data, size_t size) {
3089 data_callback(data, size, user_data);
3090 };
3091
3092 auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
3093 ->GetTaskRunners()
3094 .GetPlatformTaskRunner();
3095
3096 auto handle = new FlutterPlatformMessageResponseHandle();
3097
3098 handle->message = std::make_unique<flutter::PlatformMessage>(
3099 "", // The channel is empty and unused as the response handle is going
3100 // to referenced directly in the |FlutterEngineSendPlatformMessage|
3101 // with the container message discarded.
3102 fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
3103 std::move(platform_task_runner), response_callback));
3104 *response_out = handle;
3105 return kSuccess;
3106}

References engine, kInvalidArguments, kSuccess, LOG_EMBEDDER_ERROR, and user_data.

Referenced by FlutterDesktopMessengerSendWithReply(), FlutterEngineGetProcAddresses(), InternalSendPlatformMessage(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ FlutterPlatformMessageReleaseResponseHandle()

FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle ( FLUTTER_API_SYMBOL(FlutterEngine engine,
FlutterPlatformMessageResponseHandle response 
)

Collects the handle created using FlutterPlatformMessageCreateResponseHandle.

See also
FlutterPlatformMessageCreateResponseHandle()
Parameters
[in]engineA running engine instance.
[in]responseThe platform message response handle to collect. These handles are created using FlutterPlatformMessageCreateResponseHandle().
Returns
The result of the call.

Definition at line 3108 of file embedder.cc.

3110 {
3111 if (engine == nullptr) {
3112 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3113 }
3114
3115 if (response == nullptr) {
3116 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid response handle.");
3117 }
3118 delete response;
3119 return kSuccess;
3120}

References engine, kInvalidArguments, kSuccess, and LOG_EMBEDDER_ERROR.

Referenced by FlutterDesktopMessengerSendWithReply(), FlutterEngineGetProcAddresses(), InternalSendPlatformMessage(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ InferExternalViewEmbedderFromArgs()

static fml::StatusOr< std::unique_ptr< flutter::EmbedderExternalViewEmbedder > > InferExternalViewEmbedderFromArgs ( const FlutterCompositor compositor,
bool  enable_impeller 
)
static

Creates an EmbedderExternalViewEmbedder.

When a non-OK status is returned, engine startup should be halted.

Definition at line 1548 of file embedder.cc.

1549 {
1550 if (compositor == nullptr) {
1551 return std::unique_ptr<flutter::EmbedderExternalViewEmbedder>{nullptr};
1552 }
1553
1554 auto c_create_callback =
1555 SAFE_ACCESS(compositor, create_backing_store_callback, nullptr);
1556 auto c_collect_callback =
1557 SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr);
1558 auto c_present_callback =
1559 SAFE_ACCESS(compositor, present_layers_callback, nullptr);
1560 auto c_present_view_callback =
1561 SAFE_ACCESS(compositor, present_view_callback, nullptr);
1562 bool avoid_backing_store_cache =
1563 SAFE_ACCESS(compositor, avoid_backing_store_cache, false);
1564
1565 // Make sure the required callbacks are present
1566 if (!c_create_callback || !c_collect_callback) {
1568 "Required compositor callbacks absent.");
1569 }
1570 // Either the present view or the present layers callback must be provided.
1571 if ((!c_present_view_callback && !c_present_callback) ||
1572 (c_present_view_callback && c_present_callback)) {
1574 "Either present_layers_callback or "
1575 "present_view_callback must be provided but not both.");
1576 }
1577
1578 FlutterCompositor captured_compositor = *compositor;
1579
1581 create_render_target_callback =
1582 [captured_compositor, enable_impeller](
1583 GrDirectContext* context,
1584 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1585 const auto& config) {
1586 return CreateEmbedderRenderTarget(&captured_compositor, config,
1587 context, aiks_context,
1588 enable_impeller);
1589 };
1590
1592 if (c_present_callback) {
1593 present_callback = [c_present_callback, user_data = compositor->user_data](
1594 FlutterViewId view_id, const auto& layers) {
1595 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1596 return c_present_callback(const_cast<const FlutterLayer**>(layers.data()),
1597 layers.size(), user_data);
1598 };
1599 } else {
1600 FML_DCHECK(c_present_view_callback != nullptr);
1601 present_callback = [c_present_view_callback,
1602 user_data = compositor->user_data](
1603 FlutterViewId view_id, const auto& layers) {
1604 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1605
1606 FlutterPresentViewInfo info = {
1608 .view_id = view_id,
1609 .layers = const_cast<const FlutterLayer**>(layers.data()),
1611 .user_data = user_data,
1612 };
1613
1614 return c_present_view_callback(&info);
1615 };
1616 }
1617
1618 return std::make_unique<flutter::EmbedderExternalViewEmbedder>(
1619 avoid_backing_store_cache, create_render_target_callback,
1620 present_callback);
1621}

References context, CreateEmbedderRenderTarget(), FML_DCHECK, fml::kInvalidArgument, layers, layers_count, SAFE_ACCESS, FlutterLayer::size, FlutterPresentViewInfo::struct_size, TRACE_EVENT0, user_data, FlutterCompositor::user_data, and view_id.

Referenced by FlutterEngineInitialize().

◆ InferMetalPlatformViewCreationCallback()

static flutter::Shell::CreateCallback< flutter::PlatformView > InferMetalPlatformViewCreationCallback ( const FlutterRendererConfig config,
void *  user_data,
const flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,
std::unique_ptr< flutter::EmbedderExternalViewEmbedder external_view_embedder,
bool  enable_impeller,
impeller::Flags  impeller_flags 
)
static

Definition at line 520 of file embedder.cc.

528 {
529 if (config->type != kMetal) {
530 return nullptr;
531 }
532
533#ifdef SHELL_ENABLE_METAL
534 std::function<bool(flutter::GPUMTLTextureInfo texture)> metal_present =
535 [ptr = config->metal.present_drawable_callback,
537 FlutterMetalTexture embedder_texture;
538 embedder_texture.struct_size = sizeof(FlutterMetalTexture);
539 embedder_texture.texture = texture.texture;
540 embedder_texture.texture_id = texture.texture_id;
541 embedder_texture.user_data = texture.destruction_context;
542 embedder_texture.destruction_callback = texture.destruction_callback;
543 return ptr(user_data, &embedder_texture);
544 };
545 auto metal_get_texture =
547 const flutter::DlISize& frame_size) -> flutter::GPUMTLTextureInfo {
548 FlutterFrameInfo frame_info = {};
549 frame_info.struct_size = sizeof(FlutterFrameInfo);
550 frame_info.size = {static_cast<uint32_t>(frame_size.width),
551 static_cast<uint32_t>(frame_size.height)};
552 flutter::GPUMTLTextureInfo texture_info;
553
554 FlutterMetalTexture metal_texture = ptr(user_data, &frame_info);
555 texture_info.texture_id = metal_texture.texture_id;
556 texture_info.texture = metal_texture.texture;
557 texture_info.destruction_callback = metal_texture.destruction_callback;
558 texture_info.destruction_context = metal_texture.user_data;
559 return texture_info;
560 };
561
562 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
563 std::move(external_view_embedder);
564
565 // The static leak checker gets confused by the use of fml::MakeCopyable.
566 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
567 return fml::MakeCopyable([config, metal_present, metal_get_texture,
568 view_embedder, platform_dispatch_table,
569 enable_impeller](flutter::Shell& shell) mutable {
570 std::unique_ptr<flutter::EmbedderSurface> embedder_surface;
571
572 if (enable_impeller) {
574 metal_dispatch_table = {
575 .present = metal_present,
576 .get_texture = metal_get_texture,
577 };
578 impeller::Flags impeller_flags;
579 impeller_flags.use_sdfs = shell.GetSettings().impeller_use_sdfs;
580 embedder_surface =
581 std::make_unique<flutter::EmbedderSurfaceMetalImpeller>(
582 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
585 metal_dispatch_table, view_embedder, impeller_flags);
586 } else {
587#if !SLIMPELLER
589 metal_dispatch_table = {
590 .present = metal_present,
591 .get_texture = metal_get_texture,
592 };
593 embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetalSkia>(
594 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
597 metal_dispatch_table, view_embedder);
598#else // !SLIMPELLER
599 FML_LOG(FATAL) << "Impeller opt-out unavailable.";
600#endif // !SLIMPELLER
601 }
602
603 return std::make_unique<flutter::PlatformViewEmbedder>(
604 shell, // delegate
605 shell.GetTaskRunners(), // task runners
606 std::move(embedder_surface), // embedder surface
607 platform_dispatch_table, // platform dispatch table
608 std::move(view_embedder) // external view embedder
609 );
610 });
611#else // SHELL_ENABLE_METAL
612 FML_LOG(ERROR) << "This Flutter Engine does not support Metal rendering.";
613 return nullptr;
614#endif // SHELL_ENABLE_METAL
615}

References flutter::GPUMTLTextureInfo::destruction_callback, FlutterMetalTexture::destruction_callback, flutter::GPUMTLTextureInfo::destruction_context, FlutterMetalRendererConfig::device, FML_LOG, FlutterMetalRendererConfig::get_next_drawable_callback, flutter::Shell::GetSettings(), flutter::Shell::GetTaskRunners(), kMetal, fml::MakeCopyable(), FlutterRendererConfig::metal, flutter::EmbedderSurfaceMetalImpeller::MetalDispatchTable::present, flutter::EmbedderSurfaceMetalSkia::MetalDispatchTable::present, FlutterMetalRendererConfig::present_command_queue, FlutterMetalRendererConfig::present_drawable_callback, FlutterFrameInfo::size, FlutterFrameInfo::struct_size, FlutterMetalTexture::struct_size, flutter::GPUMTLTextureInfo::texture, FlutterMetalTexture::texture, texture, flutter::GPUMTLTextureInfo::texture_id, FlutterMetalTexture::texture_id, FlutterRendererConfig::type, impeller::Flags::use_sdfs, user_data, and FlutterMetalTexture::user_data.

Referenced by InferPlatformViewCreationCallback().

◆ InferOpenGLPlatformViewCreationCallback()

static flutter::Shell::CreateCallback< flutter::PlatformView > InferOpenGLPlatformViewCreationCallback ( const FlutterRendererConfig config,
void *  user_data,
const flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,
std::unique_ptr< flutter::EmbedderExternalViewEmbedder external_view_embedder,
bool  enable_impeller,
impeller::Flags  impeller_flags 
)
inlinestatic

Definition at line 307 of file embedder.cc.

315 {
316#ifdef SHELL_ENABLE_GL
317 if (config->type != kOpenGL) {
318 return nullptr;
319 }
320
321 auto gl_make_current = [ptr = config->open_gl.make_current,
322 user_data]() -> bool { return ptr(user_data); };
323
324 auto gl_clear_current = [ptr = config->open_gl.clear_current,
325 user_data]() -> bool { return ptr(user_data); };
326
327 auto gl_present =
328 [present = config->open_gl.present,
329 present_with_info = config->open_gl.present_with_info,
330 user_data](flutter::GLPresentInfo gl_present_info) -> bool {
331 if (present) {
332 return present(user_data);
333 } else {
334 // Format the frame and buffer damages accordingly. Note that, since the
335 // current compute damage algorithm only returns one rectangle for damage
336 // we are assuming the number of rectangles provided in frame and buffer
337 // damage are always 1. Once the function that computes damage implements
338 // support for multiple damage rectangles, GLPresentInfo should also
339 // contain the number of damage rectangles.
340
341 std::optional<FlutterRect> frame_damage_rect;
342 if (gl_present_info.frame_damage) {
343 frame_damage_rect =
344 DlIRectToFlutterRect(*(gl_present_info.frame_damage));
345 }
346 std::optional<FlutterRect> buffer_damage_rect;
347 if (gl_present_info.buffer_damage) {
348 buffer_damage_rect =
349 DlIRectToFlutterRect(*(gl_present_info.buffer_damage));
350 }
351
352 FlutterDamage frame_damage{
353 .struct_size = sizeof(FlutterDamage),
354 .num_rects = frame_damage_rect ? size_t{1} : size_t{0},
355 .damage = frame_damage_rect ? &frame_damage_rect.value() : nullptr,
356 };
357 FlutterDamage buffer_damage{
358 .struct_size = sizeof(FlutterDamage),
359 .num_rects = buffer_damage_rect ? size_t{1} : size_t{0},
360 .damage = buffer_damage_rect ? &buffer_damage_rect.value() : nullptr,
361 };
362
363 // Construct the present information concerning the frame being rendered.
364 FlutterPresentInfo present_info = {
366 .fbo_id = gl_present_info.fbo_id,
367 .frame_damage = frame_damage,
368 .buffer_damage = buffer_damage,
369 };
370
371 return present_with_info(user_data, &present_info);
372 }
373 };
374
375 auto gl_fbo_callback =
376 [fbo_callback = config->open_gl.fbo_callback,
377 fbo_with_frame_info_callback =
379 user_data](flutter::GLFrameInfo gl_frame_info) -> intptr_t {
380 if (fbo_callback) {
381 return fbo_callback(user_data);
382 } else {
383 FlutterFrameInfo frame_info = {};
384 frame_info.struct_size = sizeof(FlutterFrameInfo);
385 frame_info.size = {gl_frame_info.width, gl_frame_info.height};
386 return fbo_with_frame_info_callback(user_data, &frame_info);
387 }
388 };
389
390 auto gl_populate_existing_damage =
391 [populate_existing_damage = config->open_gl.populate_existing_damage,
392 user_data](intptr_t id) -> flutter::GLFBOInfo {
393 // If no populate_existing_damage was provided, disable partial
394 // repaint.
395 if (!populate_existing_damage) {
396 return flutter::GLFBOInfo{
397 .fbo_id = static_cast<uint32_t>(id),
398 .existing_damage = std::nullopt,
399 };
400 }
401
402 // Given the FBO's ID, get its existing damage.
403 FlutterDamage existing_damage;
404 populate_existing_damage(user_data, id, &existing_damage);
405
406 std::optional<flutter::DlIRect> existing_damage_rect = std::nullopt;
407
408 // Verify that at least one damage rectangle was provided.
409 if (existing_damage.num_rects <= 0 || existing_damage.damage == nullptr) {
410 FML_LOG(INFO) << "No damage was provided. Forcing full repaint.";
411 } else {
412 existing_damage_rect = flutter::DlIRect();
413 for (size_t i = 0; i < existing_damage.num_rects; i++) {
414 existing_damage_rect = existing_damage_rect->Union(
415 FlutterRectToDlIRect(existing_damage.damage[i]));
416 }
417 }
418
419 // Pass the information about this FBO to the rendering backend.
420 return flutter::GLFBOInfo{
421 .fbo_id = static_cast<uint32_t>(id),
422 .existing_damage = existing_damage_rect,
423 };
424 };
425
426 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
427 std::function<bool()> gl_make_resource_current_callback = nullptr;
428 if (SAFE_ACCESS(open_gl_config, make_resource_current, nullptr) != nullptr) {
429 gl_make_resource_current_callback =
430 [ptr = config->open_gl.make_resource_current, user_data]() {
431 return ptr(user_data);
432 };
433 }
434
435 std::function<flutter::DlMatrix(void)> gl_surface_transformation_callback =
436 nullptr;
437 if (SAFE_ACCESS(open_gl_config, surface_transformation, nullptr) != nullptr) {
438 gl_surface_transformation_callback =
439 [ptr = config->open_gl.surface_transformation, user_data]() {
440 FlutterTransformation transformation = ptr(user_data);
441 // clang-format off
442 return flutter::DlMatrix(
443 transformation.scaleX, transformation.skewY, 0.0f, transformation.pers0,
444 transformation.skewX, transformation.scaleY, 0.0f, transformation.pers1,
445 0.0f, 0.0f, 1.0f, 0.0f,
446 transformation.transX, transformation.transY, 0.0f, transformation.pers2
447 );
448 // clang-format on
449 };
450
451 // If there is an external view embedder, ask it to apply the surface
452 // transformation to its surfaces as well.
453 if (external_view_embedder) {
454 external_view_embedder->SetSurfaceTransformationCallback(
455 gl_surface_transformation_callback);
456 }
457 }
458
459 flutter::GPUSurfaceGLDelegate::GLProcResolver gl_proc_resolver = nullptr;
460 if (SAFE_ACCESS(open_gl_config, gl_proc_resolver, nullptr) != nullptr) {
461 gl_proc_resolver = [ptr = config->open_gl.gl_proc_resolver,
462 user_data](const char* gl_proc_name) {
463 return ptr(user_data, gl_proc_name);
464 };
465 } else {
466#if FML_OS_LINUX || FML_OS_WIN
467 gl_proc_resolver = DefaultGLProcResolver;
468#endif // FML_OS_LINUX || FML_OS_WIN
469 }
470
471 bool fbo_reset_after_present =
472 SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false);
473
475 gl_make_current, // gl_make_current_callback
476 gl_clear_current, // gl_clear_current_callback
477 gl_present, // gl_present_callback
478 gl_fbo_callback, // gl_fbo_callback
479 gl_make_resource_current_callback, // gl_make_resource_current_callback
480 gl_surface_transformation_callback, // gl_surface_transformation_callback
481 gl_proc_resolver, // gl_proc_resolver
482 gl_populate_existing_damage, // gl_populate_existing_damage
483 };
484
485 return fml::MakeCopyable(
486 [gl_dispatch_table, fbo_reset_after_present, platform_dispatch_table,
487 enable_impeller, impeller_flags,
488 external_view_embedder =
489 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
490 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
491 std::move(external_view_embedder);
492 if (enable_impeller) {
493 return std::make_unique<flutter::PlatformViewEmbedder>(
494 shell, // delegate
495 shell.GetTaskRunners(), // task runners
496 std::make_unique<flutter::EmbedderSurfaceGLImpeller>(
497 gl_dispatch_table, fbo_reset_after_present, view_embedder,
498 impeller_flags), // embedder_surface
499 platform_dispatch_table, // embedder platform dispatch table
500 view_embedder // external view embedder
501 );
502 }
503 return std::make_unique<flutter::PlatformViewEmbedder>(
504 shell, // delegate
505 shell.GetTaskRunners(), // task runners
506 std::make_unique<flutter::EmbedderSurfaceGLSkia>(
507 gl_dispatch_table, fbo_reset_after_present,
508 view_embedder), // embedder_surface
509 platform_dispatch_table, // embedder platform dispatch table
510 view_embedder // external view embedder
511 );
512 });
513#else // SHELL_ENABLE_GL
514 FML_LOG(ERROR) << "This Flutter Engine does not support OpenGL rendering.";
515 return nullptr;
516#endif // SHELL_ENABLE_GL
517}

References FlutterOpenGLRendererConfig::clear_current, FlutterDamage::damage, FlutterOpenGLRendererConfig::fbo_callback, flutter::GLFBOInfo::fbo_id, FlutterOpenGLRendererConfig::fbo_with_frame_info_callback, FML_LOG, flutter::Shell::GetTaskRunners(), FlutterOpenGLRendererConfig::gl_proc_resolver, i, id, kOpenGL, FlutterOpenGLRendererConfig::make_current, FlutterOpenGLRendererConfig::make_resource_current, fml::MakeCopyable(), FlutterDamage::num_rects, FlutterRendererConfig::open_gl, FlutterTransformation::pers0, FlutterTransformation::pers1, FlutterTransformation::pers2, FlutterOpenGLRendererConfig::populate_existing_damage, FlutterOpenGLRendererConfig::present, FlutterOpenGLRendererConfig::present_with_info, SAFE_ACCESS, FlutterTransformation::scaleX, FlutterTransformation::scaleY, FlutterFrameInfo::size, FlutterTransformation::skewX, FlutterTransformation::skewY, FlutterDamage::struct_size, FlutterFrameInfo::struct_size, FlutterPresentInfo::struct_size, FlutterOpenGLRendererConfig::surface_transformation, FlutterTransformation::transX, FlutterTransformation::transY, FlutterRendererConfig::type, user_data, and FlutterUIntSize::width.

Referenced by InferPlatformViewCreationCallback().

◆ InferPlatformViewCreationCallback()

static flutter::Shell::CreateCallback< flutter::PlatformView > InferPlatformViewCreationCallback ( const FlutterRendererConfig config,
void *  user_data,
const flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,
std::unique_ptr< flutter::EmbedderExternalViewEmbedder external_view_embedder,
bool  enable_impeller,
impeller::Flags  impeller_flags 
)
static

Definition at line 819 of file embedder.cc.

827 {
828 if (config == nullptr) {
829 return nullptr;
830 }
831
832 switch (config->type) {
833 case kOpenGL:
835 config, user_data, platform_dispatch_table,
836 std::move(external_view_embedder), enable_impeller, impeller_flags);
837 case kSoftware:
839 config, user_data, platform_dispatch_table,
840 std::move(external_view_embedder));
841 case kMetal:
843 config, user_data, platform_dispatch_table,
844 std::move(external_view_embedder), enable_impeller, impeller_flags);
845 case kVulkan:
847 config, user_data, platform_dispatch_table,
848 std::move(external_view_embedder), enable_impeller, impeller_flags);
849 default:
850 return nullptr;
851 }
852 return nullptr;
853}

References InferMetalPlatformViewCreationCallback(), InferOpenGLPlatformViewCreationCallback(), InferSoftwarePlatformViewCreationCallback(), InferVulkanPlatformViewCreationCallback(), kMetal, kOpenGL, kSoftware, kVulkan, FlutterRendererConfig::type, and user_data.

Referenced by FlutterEngineInitialize().

◆ InferSoftwarePlatformViewCreationCallback()

static flutter::Shell::CreateCallback< flutter::PlatformView > InferSoftwarePlatformViewCreationCallback ( const FlutterRendererConfig config,
void *  user_data,
const flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,
std::unique_ptr< flutter::EmbedderExternalViewEmbedder external_view_embedder 
)
static

Definition at line 782 of file embedder.cc.

788 {
789 if (config->type != kSoftware) {
790 return nullptr;
791 }
792
793 auto software_present_backing_store =
795 const void* allocation, size_t row_bytes, size_t height) -> bool {
796 return ptr(user_data, allocation, row_bytes, height);
797 };
798
800 software_dispatch_table = {
801 software_present_backing_store, // required
802 };
803
804 return fml::MakeCopyable(
805 [software_dispatch_table, platform_dispatch_table,
806 external_view_embedder =
807 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
808 return std::make_unique<flutter::PlatformViewEmbedder>(
809 shell, // delegate
810 shell.GetTaskRunners(), // task runners
811 software_dispatch_table, // software dispatch table
812 platform_dispatch_table, // platform dispatch table
813 std::move(external_view_embedder) // external view embedder
814 );
815 });
816}

References flutter::Shell::GetTaskRunners(), height, kSoftware, fml::MakeCopyable(), FlutterRendererConfig::software, FlutterSoftwareRendererConfig::surface_present_callback, FlutterRendererConfig::type, and user_data.

Referenced by InferPlatformViewCreationCallback().

◆ InferVulkanPlatformViewCreationCallback()

static flutter::Shell::CreateCallback< flutter::PlatformView > InferVulkanPlatformViewCreationCallback ( const FlutterRendererConfig config,
void *  user_data,
const flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table,
std::unique_ptr< flutter::EmbedderExternalViewEmbedder external_view_embedder,
bool  enable_impeller,
impeller::Flags  impeller_flags 
)
static

Definition at line 618 of file embedder.cc.

626 {
627 if (config->type != kVulkan) {
628 return nullptr;
629 }
630
631#ifdef SHELL_ENABLE_VULKAN
632 std::function<void*(VkInstance, const char*)>
633 vulkan_get_instance_proc_address =
635 VkInstance instance, const char* proc_name) -> void* {
636 return ptr(user_data, instance, proc_name);
637 };
638
639 auto vulkan_get_next_image =
640 [ptr = config->vulkan.get_next_image_callback,
641 user_data](const flutter::DlISize& frame_size) -> FlutterVulkanImage {
642 FlutterFrameInfo frame_info = {
643 .struct_size = sizeof(FlutterFrameInfo),
644 .size = {static_cast<uint32_t>(frame_size.width),
645 static_cast<uint32_t>(frame_size.height)},
646 };
647
648 return ptr(user_data, &frame_info);
649 };
650
651 auto vulkan_present_image_callback =
652 [ptr = config->vulkan.present_image_callback, user_data](
653 VkImage image, VkFormat format) -> bool {
654 FlutterVulkanImage image_desc = {
656 .image = reinterpret_cast<uint64_t>(image),
657 .format = static_cast<uint32_t>(format),
658 };
659 return ptr(user_data, &image_desc);
660 };
661
662 auto vk_instance = static_cast<VkInstance>(config->vulkan.instance);
663 auto proc_addr =
664 vulkan_get_instance_proc_address(vk_instance, "vkGetInstanceProcAddr");
665
666 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
667 std::move(external_view_embedder);
668
669#if IMPELLER_SUPPORTS_RENDERING
670 if (enable_impeller) {
672 vulkan_dispatch_table = {
674 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
675 .get_next_image = vulkan_get_next_image,
676 .present_image = vulkan_present_image_callback,
677 };
678
679 std::unique_ptr<flutter::EmbedderSurfaceVulkanImpeller> embedder_surface =
680 std::make_unique<flutter::EmbedderSurfaceVulkanImpeller>(
681 config->vulkan.version, vk_instance,
686 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
687 static_cast<VkDevice>(config->vulkan.device),
689 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
690 view_embedder, impeller_flags);
691
692 return fml::MakeCopyable(
693 [embedder_surface = std::move(embedder_surface),
694 platform_dispatch_table,
695 external_view_embedder =
696 std::move(view_embedder)](flutter::Shell& shell) mutable {
697 return std::make_unique<flutter::PlatformViewEmbedder>(
698 shell, // delegate
699 shell.GetTaskRunners(), // task runners
700 std::move(embedder_surface), // embedder surface
701 platform_dispatch_table, // platform dispatch table
702 std::move(external_view_embedder) // external view embedder
703 );
704 });
705 } else {
707 {
709 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
710 .get_next_image = vulkan_get_next_image,
711 .present_image = vulkan_present_image_callback,
712 };
713
714 std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
715 std::make_unique<flutter::EmbedderSurfaceVulkan>(
716 config->vulkan.version, vk_instance,
721 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
722 static_cast<VkDevice>(config->vulkan.device),
724 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
725 view_embedder);
726
727 return fml::MakeCopyable(
728 [embedder_surface = std::move(embedder_surface),
729 platform_dispatch_table,
730 external_view_embedder =
731 std::move(view_embedder)](flutter::Shell& shell) mutable {
732 return std::make_unique<flutter::PlatformViewEmbedder>(
733 shell, // delegate
734 shell.GetTaskRunners(), // task runners
735 std::move(embedder_surface), // embedder surface
736 platform_dispatch_table, // platform dispatch table
737 std::move(external_view_embedder) // external view embedder
738 );
739 });
740 }
741#else
744 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
745 .get_next_image = vulkan_get_next_image,
746 .present_image = vulkan_present_image_callback,
747 };
748
749 std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
750 std::make_unique<flutter::EmbedderSurfaceVulkan>(
751 config->vulkan.version, vk_instance,
756 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
757 static_cast<VkDevice>(config->vulkan.device),
759 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
760 view_embedder);
761
762 return fml::MakeCopyable(
763 [embedder_surface = std::move(embedder_surface), platform_dispatch_table,
764 external_view_embedder =
765 std::move(view_embedder)](flutter::Shell& shell) mutable {
766 return std::make_unique<flutter::PlatformViewEmbedder>(
767 shell, // delegate
768 shell.GetTaskRunners(), // task runners
769 std::move(embedder_surface), // embedder surface
770 platform_dispatch_table, // platform dispatch table
771 std::move(external_view_embedder) // external view embedder
772 );
773 });
774#endif // // IMPELLER_SUPPORTS_RENDERING
775#else // SHELL_ENABLE_VULKAN
776 FML_LOG(ERROR) << "This Flutter Engine does not support Vulkan rendering.";
777 return nullptr;
778#endif // SHELL_ENABLE_VULKAN
779}

References FlutterVulkanRendererConfig::device, FlutterVulkanRendererConfig::enabled_device_extension_count, FlutterVulkanRendererConfig::enabled_device_extensions, FlutterVulkanRendererConfig::enabled_instance_extension_count, FlutterVulkanRendererConfig::enabled_instance_extensions, FML_LOG, FlutterVulkanImage::format, format, flutter::EmbedderSurfaceVulkan::VulkanDispatchTable::get_instance_proc_address, flutter::EmbedderSurfaceVulkanImpeller::VulkanDispatchTable::get_instance_proc_address, FlutterVulkanRendererConfig::get_instance_proc_address_callback, FlutterVulkanRendererConfig::get_next_image_callback, flutter::Shell::GetTaskRunners(), image, instance, FlutterVulkanRendererConfig::instance, kVulkan, fml::MakeCopyable(), FlutterVulkanRendererConfig::physical_device, FlutterVulkanRendererConfig::present_image_callback, FlutterVulkanRendererConfig::queue, FlutterVulkanRendererConfig::queue_family_index, FlutterFrameInfo::struct_size, FlutterVulkanImage::struct_size, FlutterRendererConfig::type, user_data, FlutterVulkanRendererConfig::version, and FlutterRendererConfig::vulkan.

Referenced by InferPlatformViewCreationCallback().

◆ InternalSendPlatformMessage()

static FlutterEngineResult InternalSendPlatformMessage ( FLUTTER_API_SYMBOL(FlutterEngine engine,
const char *  channel,
const uint8_t *  data,
size_t  size,
FlutterDataCallback  data_callback,
void *  user_data 
)
static

Definition at line 2930 of file embedder.cc.

2936 {
2937 FlutterEngineResult result;
2938
2939 FlutterPlatformMessageResponseHandle* response_handle;
2941 engine, data_callback, user_data, &response_handle);
2942 if (result != kSuccess) {
2943 return result;
2944 }
2945
2947 sizeof(FlutterPlatformMessage), // struct_size
2948 channel, // channel
2949 data, // message
2950 size, // message_size
2951 response_handle, // response_handle
2952 };
2953
2955 // Whether `SendPlatformMessage` succeeds or not, the response handle must be
2956 // released.
2957 FlutterEngineResult release_result =
2959 if (result != kSuccess) {
2960 return result;
2961 }
2962
2963 return release_result;
2964}

References channel, engine, FlutterEngineSendPlatformMessage(), FlutterPlatformMessageCreateResponseHandle(), FlutterPlatformMessageReleaseResponseHandle(), kSuccess, message, and user_data.

Referenced by FlutterEngineSendKeyEvent().

◆ IsMetalRendererConfigValid()

static bool IsMetalRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 193 of file embedder.cc.

193 {
194 if (config->type != kMetal) {
195 return false;
196 }
197
198 const FlutterMetalRendererConfig* metal_config = &config->metal;
199
200 bool device = SAFE_ACCESS(metal_config, device, nullptr);
201 bool command_queue =
202 SAFE_ACCESS(metal_config, present_command_queue, nullptr);
203
204 bool present = SAFE_ACCESS(metal_config, present_drawable_callback, nullptr);
205 bool get_texture =
206 SAFE_ACCESS(metal_config, get_next_drawable_callback, nullptr);
207
208 return device && command_queue && present && get_texture;
209}

References device, kMetal, FlutterRendererConfig::metal, SAFE_ACCESS, and FlutterRendererConfig::type.

Referenced by IsRendererValid().

◆ IsOpenGLRendererConfigValid()

static bool IsOpenGLRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 160 of file embedder.cc.

160 {
161 if (config->type != kOpenGL) {
162 return false;
163 }
164
165 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
166
167 if (!SAFE_EXISTS(open_gl_config, make_current) ||
168 !SAFE_EXISTS(open_gl_config, clear_current) ||
169 !SAFE_EXISTS_ONE_OF(open_gl_config, fbo_callback,
170 fbo_with_frame_info_callback) ||
171 !SAFE_EXISTS_ONE_OF(open_gl_config, present, present_with_info)) {
172 return false;
173 }
174
175 return true;
176}

References kOpenGL, FlutterRendererConfig::open_gl, SAFE_EXISTS, SAFE_EXISTS_ONE_OF, and FlutterRendererConfig::type.

Referenced by IsRendererValid().

◆ IsRendererValid()

static bool IsRendererValid ( const FlutterRendererConfig config)
static

Definition at line 231 of file embedder.cc.

231 {
232 if (config == nullptr) {
233 return false;
234 }
235
236 switch (config->type) {
237 case kOpenGL:
238 return IsOpenGLRendererConfigValid(config);
239 case kSoftware:
240 return IsSoftwareRendererConfigValid(config);
241 case kMetal:
242 return IsMetalRendererConfigValid(config);
243 case kVulkan:
244 return IsVulkanRendererConfigValid(config);
245 default:
246 return false;
247 }
248
249 return false;
250}

References IsMetalRendererConfigValid(), IsOpenGLRendererConfigValid(), IsSoftwareRendererConfigValid(), IsVulkanRendererConfigValid(), kMetal, kOpenGL, kSoftware, kVulkan, and FlutterRendererConfig::type.

Referenced by FlutterEngineInitialize().

◆ IsSoftwareRendererConfigValid()

static bool IsSoftwareRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 178 of file embedder.cc.

178 {
179 if (config->type != kSoftware) {
180 return false;
181 }
182
183 const FlutterSoftwareRendererConfig* software_config = &config->software;
184
185 if (SAFE_ACCESS(software_config, surface_present_callback, nullptr) ==
186 nullptr) {
187 return false;
188 }
189
190 return true;
191}

References kSoftware, SAFE_ACCESS, FlutterRendererConfig::software, and FlutterRendererConfig::type.

Referenced by IsRendererValid().

◆ IsVulkanRendererConfigValid()

static bool IsVulkanRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 211 of file embedder.cc.

211 {
212 if (config->type != kVulkan) {
213 return false;
214 }
215
216 const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan;
217
218 if (!SAFE_EXISTS(vulkan_config, instance) ||
219 !SAFE_EXISTS(vulkan_config, physical_device) ||
220 !SAFE_EXISTS(vulkan_config, device) ||
221 !SAFE_EXISTS(vulkan_config, queue) ||
222 !SAFE_EXISTS(vulkan_config, get_instance_proc_address_callback) ||
223 !SAFE_EXISTS(vulkan_config, get_next_image_callback) ||
224 !SAFE_EXISTS(vulkan_config, present_image_callback)) {
225 return false;
226 }
227
228 return true;
229}

References device, instance, kVulkan, physical_device, queue, SAFE_EXISTS, FlutterRendererConfig::type, and FlutterRendererConfig::vulkan.

Referenced by IsRendererValid().

◆ LogEmbedderError()

static FlutterEngineResult LogEmbedderError ( FlutterEngineResult  code,
const char *  reason,
const char *  code_name,
const char *  function,
const char *  file,
int  line 
)
static

Definition at line 136 of file embedder.cc.

141 {
142#if FML_OS_WIN
143 constexpr char kSeparator = '\\';
144#else
145 constexpr char kSeparator = '/';
146#endif
147 const auto file_base =
148 (::strrchr(file, kSeparator) ? strrchr(file, kSeparator) + 1 : file);
149 char error[256] = {};
150 snprintf(error, (sizeof(error) / sizeof(char)),
151 "%s (%d): '%s' returned '%s'. %s", file_base, line, function,
152 code_name, reason);
153 std::cerr << error << std::endl;
154 return code;
155}

References error, and function.

◆ MakeRenderTargetFromBackingStoreImpeller() [1/2]

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 
)
static

Definition at line 1242 of file embedder.cc.

1247 {
1248#if defined(SHELL_ENABLE_METAL) && defined(IMPELLER_SUPPORTS_RENDERING)
1249 if (!metal->texture.texture) {
1250 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
1251 return nullptr;
1252 }
1253
1254 const auto size = impeller::ISize(config.size.width, config.size.height);
1255
1256 impeller::TextureDescriptor resolve_tex_desc;
1257 resolve_tex_desc.size = size;
1260 resolve_tex_desc.usage = impeller::TextureUsage::kRenderTarget |
1262
1263 auto resolve_tex = impeller::WrapTextureMTL(
1264 resolve_tex_desc, metal->texture.texture,
1266 user_data = metal->texture.user_data]() { callback(user_data); });
1267 if (!resolve_tex) {
1268 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
1269 return nullptr;
1270 }
1271
1272 aiks_context->GetContext()->UpdateOffscreenLayerPixelFormat(
1273 resolve_tex->GetTextureDescriptor().format);
1274
1275 resolve_tex->SetLabel("ImpellerBackingStoreResolve");
1276
1277 impeller::TextureDescriptor msaa_tex_desc;
1281 msaa_tex_desc.format = resolve_tex->GetTextureDescriptor().format;
1282 msaa_tex_desc.size = size;
1284
1285 auto msaa_tex =
1286 aiks_context->GetContext()->GetResourceAllocator()->CreateTexture(
1287 msaa_tex_desc);
1288 if (!msaa_tex) {
1289 FML_LOG(ERROR) << "Could not allocate MSAA color texture.";
1290 return nullptr;
1291 }
1292 msaa_tex->SetLabel("ImpellerBackingStoreColorMSAA");
1293
1295 color0.texture = msaa_tex;
1299 color0.resolve_texture = resolve_tex;
1300
1301 impeller::RenderTarget render_target_desc;
1302 render_target_desc.SetColorAttachment(color0, 0u);
1303
1304 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1305 backing_store, aiks_context,
1306 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1307 on_release, fml::closure());
1308#else
1309 return nullptr;
1310#endif
1311}

References callback, impeller::ColorAttachment::clear_color, impeller::Color::DarkSlateGray(), FlutterMetalTexture::destruction_callback, FML_LOG, impeller::TextureDescriptor::format, FlutterSize::height, impeller::kClear, impeller::kCount1, impeller::kCount4, impeller::kDevicePrivate, impeller::kDeviceTransient, impeller::kMultisampleResolve, impeller::kRenderTarget, impeller::kShaderRead, impeller::kTexture2DMultisample, impeller::Attachment::load_action, impeller::Attachment::resolve_texture, impeller::TextureDescriptor::sample_count, impeller::RenderTarget::SetColorAttachment(), impeller::TextureDescriptor::size, FlutterBackingStoreConfig::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, FlutterMetalTexture::texture, FlutterMetalBackingStore::texture, impeller::TextureDescriptor::type, impeller::TextureDescriptor::usage, user_data, FlutterMetalTexture::user_data, FlutterSize::width, and impeller::WrapTextureMTL().

◆ MakeRenderTargetFromBackingStoreImpeller() [2/2]

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 FlutterOpenGLFramebuffer framebuffer 
)
static

Definition at line 1148 of file embedder.cc.

1153 {
1154#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
1155 auto format = FlutterFormatToImpellerPixelFormat(framebuffer->target);
1156 if (!format.has_value()) {
1157 return nullptr;
1158 }
1159
1160 const auto& gl_context =
1161 impeller::ContextGLES::Cast(*aiks_context->GetContext());
1162 const bool implicit_msaa = aiks_context->GetContext()
1163 ->GetCapabilities()
1164 ->SupportsImplicitResolvingMSAA();
1165 const auto size = impeller::ISize(config.size.width, config.size.height);
1166
1167 impeller::TextureDescriptor color0_tex;
1168 if (implicit_msaa) {
1171 } else {
1174 }
1175 color0_tex.format = format.value();
1176 color0_tex.size = size;
1177 color0_tex.usage = static_cast<impeller::TextureUsageMask>(
1180
1183 gl_context.GetReactor(), color0_tex, framebuffer->name);
1186 if (implicit_msaa) {
1188 color0.resolve_texture = color0.texture;
1189 } else {
1191 }
1192
1193 impeller::TextureDescriptor depth_stencil_texture_desc;
1194 depth_stencil_texture_desc.format = impeller::PixelFormat::kD24UnormS8Uint;
1195 depth_stencil_texture_desc.size = size;
1196 depth_stencil_texture_desc.usage = static_cast<impeller::TextureUsageMask>(
1198 if (implicit_msaa) {
1199 depth_stencil_texture_desc.type =
1201 depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount4;
1202 } else {
1203 depth_stencil_texture_desc.type = impeller::TextureType::kTexture2D;
1204 depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount1;
1205 }
1206
1207 auto depth_stencil_tex = impeller::TextureGLES::CreatePlaceholder(
1208 gl_context.GetReactor(), depth_stencil_texture_desc);
1209
1211 depth0.clear_depth = 0;
1212 depth0.texture = depth_stencil_tex;
1215
1217 stencil0.clear_stencil = 0;
1218 stencil0.texture = depth_stencil_tex;
1221
1222 impeller::RenderTarget render_target_desc;
1223
1224 render_target_desc.SetColorAttachment(color0, 0u);
1225 render_target_desc.SetDepthAttachment(depth0);
1226 render_target_desc.SetStencilAttachment(stencil0);
1227
1228 fml::closure framebuffer_destruct =
1229 [callback = framebuffer->destruction_callback,
1230 user_data = framebuffer->user_data]() { callback(user_data); };
1231
1232 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1233 backing_store, aiks_context,
1234 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1235 on_release, framebuffer_destruct);
1236#else
1237 return nullptr;
1238#endif
1239}

References callback, impeller::BackendCast< ContextGLES, Context >::Cast(), impeller::ColorAttachment::clear_color, impeller::DepthAttachment::clear_depth, impeller::StencilAttachment::clear_stencil, impeller::TextureGLES::CreatePlaceholder(), impeller::Color::DarkSlateGray(), impeller::TextureDescriptor::format, format, framebuffer, FlutterSize::height, impeller::kClear, impeller::kCount1, impeller::kCount4, impeller::kD24UnormS8Uint, impeller::kDevicePrivate, impeller::kDontCare, impeller::kMultisampleResolve, impeller::kRenderTarget, impeller::kStore, impeller::kTexture2D, impeller::kTexture2DMultisample, impeller::Attachment::load_action, impeller::Attachment::resolve_texture, impeller::TextureDescriptor::sample_count, impeller::RenderTarget::SetColorAttachment(), impeller::RenderTarget::SetDepthAttachment(), impeller::RenderTarget::SetStencilAttachment(), impeller::TextureDescriptor::size, FlutterBackingStoreConfig::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, impeller::TextureDescriptor::type, impeller::TextureDescriptor::usage, user_data, FlutterSize::width, and impeller::TextureGLES::WrapFBO().

Referenced by CreateEmbedderRenderTarget().

◆ MakeRenderTargetFromSkSurface() [1/2]

static std::unique_ptr< flutter::EmbedderRenderTarget > MakeRenderTargetFromSkSurface ( FlutterBackingStore  backing_store,
sk_sp< SkSurface >  skia_surface,
fml::closure  on_release 
)
static

Definition at line 1381 of file embedder.cc.

1383 {
1384 return MakeRenderTargetFromSkSurface(backing_store, std::move(skia_surface),
1385 std::move(on_release), nullptr, nullptr);
1386}

References MakeRenderTargetFromSkSurface().

◆ MakeRenderTargetFromSkSurface() [2/2]

static std::unique_ptr< flutter::EmbedderRenderTarget > MakeRenderTargetFromSkSurface ( FlutterBackingStore  backing_store,
sk_sp< SkSurface >  skia_surface,
fml::closure  on_release,
flutter::EmbedderRenderTarget::MakeOrClearCurrentCallback  on_make_current,
flutter::EmbedderRenderTarget::MakeOrClearCurrentCallback  on_clear_current 
)
static

Definition at line 1365 of file embedder.cc.

1371 {
1372 if (!skia_surface) {
1373 return nullptr;
1374 }
1375 return std::make_unique<flutter::EmbedderRenderTargetSkia>(
1376 backing_store, std::move(skia_surface), std::move(on_release),
1377 std::move(on_make_current), std::move(on_clear_current));
1378}

Referenced by CreateEmbedderRenderTarget(), and MakeRenderTargetFromSkSurface().

◆ MakeSkSurfaceFromBackingStore() [1/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterMetalBackingStore metal 
)
static

Definition at line 1084 of file embedder.cc.

1087 {
1088#if defined(SHELL_ENABLE_METAL) && !SLIMPELLER
1089 GrMtlTextureInfo texture_info;
1090 if (!metal->texture.texture) {
1091 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
1092 return nullptr;
1093 }
1094 sk_cfp<FlutterMetalTextureHandle> mtl_texture;
1095 mtl_texture.retain(metal->texture.texture);
1096 texture_info.fTexture = mtl_texture;
1097 GrBackendTexture backend_texture =
1098 GrBackendTextures::MakeMtl(config.size.width, //
1099 config.size.height, //
1100 skgpu::Mipmapped::kNo, //
1101 texture_info //
1102 );
1103
1104 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
1105
1106 auto surface = SkSurfaces::WrapBackendTexture(
1107 context, // context
1108 backend_texture, // back-end texture
1109 kTopLeft_GrSurfaceOrigin, // surface origin
1110 1, // sample count
1111 kBGRA_8888_SkColorType, // color type
1112 nullptr, // color space
1113 &surface_properties, // surface properties
1114 static_cast<SkSurfaces::TextureReleaseProc>(
1115 metal->texture.destruction_callback), // release proc
1116 metal->texture.user_data // release context
1117 );
1118
1119 if (!surface) {
1120 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
1121 return nullptr;
1122 }
1123
1124 return surface;
1125#else
1126 return nullptr;
1127#endif
1128}

References context, FlutterMetalTexture::destruction_callback, FML_LOG, FlutterSize::height, FlutterBackingStoreConfig::size, surface, FlutterMetalTexture::texture, FlutterMetalBackingStore::texture, FlutterMetalTexture::user_data, and FlutterSize::width.

◆ MakeSkSurfaceFromBackingStore() [2/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterOpenGLFramebuffer framebuffer 
)
static

Definition at line 901 of file embedder.cc.

904 {
905#ifdef SHELL_ENABLE_GL
906 GrGLFramebufferInfo framebuffer_info = {};
907 framebuffer_info.fFormat = framebuffer->target;
908 framebuffer_info.fFBOID = framebuffer->name;
909
910 auto backend_render_target =
911 GrBackendRenderTargets::MakeGL(config.size.width, // width
912 config.size.height, // height
913 1, // sample count
914 0, // stencil bits
915 framebuffer_info // framebuffer info
916 );
917
918 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
919
920 std::optional<SkColorType> color_type =
921 FlutterFormatToSkColorType(framebuffer->target);
922 if (!color_type) {
923 return nullptr;
924 }
925
926 auto surface = SkSurfaces::WrapBackendRenderTarget(
927 context, // context
928 backend_render_target, // backend render target
929 kBottomLeft_GrSurfaceOrigin, // surface origin
930 color_type.value(), // color type
931 SkColorSpace::MakeSRGB(), // color space
932 &surface_properties, // surface properties
933 static_cast<SkSurfaces::RenderTargetReleaseProc>(
934 framebuffer->destruction_callback), // release proc
935 framebuffer->user_data // release context
936 );
937
938 if (!surface) {
939 FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
940 return nullptr;
941 }
942 return surface;
943#else
944 return nullptr;
945#endif
946}

References color_type, context, FML_LOG, framebuffer, FlutterSize::height, FlutterBackingStoreConfig::size, surface, and FlutterSize::width.

◆ MakeSkSurfaceFromBackingStore() [3/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterOpenGLSurface surface 
)
static

Definition at line 948 of file embedder.cc.

951 {
952#ifdef SHELL_ENABLE_GL
953 GrGLFramebufferInfo framebuffer_info = {};
954 framebuffer_info.fFormat = SAFE_ACCESS(surface, format, GL_BGRA8_EXT);
955 framebuffer_info.fFBOID = 0;
956
957 auto backend_render_target =
958 GrBackendRenderTargets::MakeGL(config.size.width, // width
959 config.size.height, // height
960 1, // sample count
961 0, // stencil bits
962 framebuffer_info // framebuffer info
963 );
964
965 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
966
967 std::optional<SkColorType> color_type =
968 FlutterFormatToSkColorType(surface->format);
969 if (!color_type) {
970 return nullptr;
971 }
972
973 auto sk_surface = SkSurfaces::WrapBackendRenderTarget(
974 context, // context
975 backend_render_target, // backend render target
976 kBottomLeft_GrSurfaceOrigin, // surface origin
977 color_type.value(), // color type
978 SkColorSpace::MakeSRGB(), // color space
979 &surface_properties, // surface properties
980 static_cast<SkSurfaces::RenderTargetReleaseProc>(
981 surface->destruction_callback), // release proc
982 surface->user_data // release context
983 );
984
985 if (!sk_surface) {
986 FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
987 return nullptr;
988 }
989 return sk_surface;
990#else
991 return nullptr;
992#endif
993}

References color_type, context, FML_LOG, format, FlutterSize::height, SAFE_ACCESS, FlutterBackingStoreConfig::size, surface, and FlutterSize::width.

◆ MakeSkSurfaceFromBackingStore() [4/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterOpenGLTexture texture 
)
static

Definition at line 855 of file embedder.cc.

858 {
859#ifdef SHELL_ENABLE_GL
860 GrGLTextureInfo texture_info;
861 texture_info.fTarget = texture->target;
862 texture_info.fID = texture->name;
863 texture_info.fFormat = texture->format;
864
865 GrBackendTexture backend_texture =
866 GrBackendTextures::MakeGL(config.size.width, config.size.height,
867 skgpu::Mipmapped::kNo, texture_info);
868
869 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
870
871 std::optional<SkColorType> color_type =
872 FlutterFormatToSkColorType(texture->format);
873 if (!color_type) {
874 return nullptr;
875 }
876
877 auto surface = SkSurfaces::WrapBackendTexture(
878 context, // context
879 backend_texture, // back-end texture
880 kBottomLeft_GrSurfaceOrigin, // surface origin
881 1, // sample count
882 color_type.value(), // color type
883 SkColorSpace::MakeSRGB(), // color space
884 &surface_properties, // surface properties
885 static_cast<SkSurfaces::TextureReleaseProc>(
886 texture->destruction_callback), // release proc
887 texture->user_data // release context
888 );
889
890 if (!surface) {
891 FML_LOG(ERROR) << "Could not wrap embedder supplied render texture.";
892 return nullptr;
893 }
894
895 return surface;
896#else
897 return nullptr;
898#endif
899}

References color_type, context, FML_LOG, FlutterSize::height, FlutterBackingStoreConfig::size, surface, texture, and FlutterSize::width.

Referenced by CreateEmbedderRenderTarget().

◆ MakeSkSurfaceFromBackingStore() [5/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterSoftwareBackingStore software 
)
static

Definition at line 995 of file embedder.cc.

998 {
999 const auto image_info =
1000 SkImageInfo::MakeN32Premul(config.size.width, config.size.height);
1001
1002 struct Captures {
1003 VoidCallback destruction_callback;
1004 void* user_data;
1005 };
1006 auto captures = std::make_unique<Captures>();
1007 captures->destruction_callback = software->destruction_callback;
1008 captures->user_data = software->user_data;
1009 auto release_proc = [](void* pixels, void* context) {
1010 auto captures = reinterpret_cast<Captures*>(context);
1011 if (captures->destruction_callback) {
1012 captures->destruction_callback(captures->user_data);
1013 }
1014 delete captures;
1015 };
1016
1017 auto surface =
1018 SkSurfaces::WrapPixels(image_info, // image info
1019 const_cast<void*>(software->allocation), // pixels
1020 software->row_bytes, // row bytes
1021 release_proc, // release proc
1022 captures.get() // get context
1023 );
1024
1025 if (!surface) {
1026 FML_LOG(ERROR)
1027 << "Could not wrap embedder supplied software render buffer.";
1028 if (software->destruction_callback) {
1029 software->destruction_callback(software->user_data);
1030 }
1031 return nullptr;
1032 }
1033 if (surface) {
1034 captures.release(); // Skia has assumed ownership of the struct.
1035 }
1036 return surface;
1037}

References FlutterSoftwareBackingStore::allocation, context, FlutterSoftwareBackingStore::destruction_callback, FML_LOG, FlutterSize::height, FlutterSoftwareBackingStore::row_bytes, FlutterBackingStoreConfig::size, surface, user_data, FlutterSoftwareBackingStore::user_data, and FlutterSize::width.

◆ MakeSkSurfaceFromBackingStore() [6/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterSoftwareBackingStore2 software 
)
static

Definition at line 1039 of file embedder.cc.

1042 {
1043 const auto color_info = getSkColorInfo(software->pixel_format);
1044 if (!color_info) {
1045 return nullptr;
1046 }
1047
1048 const auto image_info = SkImageInfo::Make(
1049 SkISize::Make(config.size.width, config.size.height), *color_info);
1050
1051 struct Captures {
1052 VoidCallback destruction_callback;
1053 void* user_data;
1054 };
1055 auto captures = std::make_unique<Captures>();
1056 captures->destruction_callback = software->destruction_callback;
1057 captures->user_data = software->user_data;
1058 auto release_proc = [](void* pixels, void* context) {
1059 auto captures = reinterpret_cast<Captures*>(context);
1060 if (captures->destruction_callback) {
1061 captures->destruction_callback(captures->user_data);
1062 }
1063 };
1064
1065 auto surface =
1066 SkSurfaces::WrapPixels(image_info, // image info
1067 const_cast<void*>(software->allocation), // pixels
1068 software->row_bytes, // row bytes
1069 release_proc, // release proc
1070 captures.release() // release context
1071 );
1072
1073 if (!surface) {
1074 FML_LOG(ERROR)
1075 << "Could not wrap embedder supplied software render buffer.";
1076 if (software->destruction_callback) {
1077 software->destruction_callback(software->user_data);
1078 }
1079 return nullptr;
1080 }
1081 return surface;
1082}

References FlutterSoftwareBackingStore2::allocation, context, FlutterSoftwareBackingStore2::destruction_callback, FML_LOG, getSkColorInfo(), FlutterSize::height, FlutterSoftwareBackingStore2::pixel_format, FlutterSoftwareBackingStore2::row_bytes, FlutterBackingStoreConfig::size, surface, user_data, FlutterSoftwareBackingStore2::user_data, and FlutterSize::width.

◆ MakeSkSurfaceFromBackingStore() [7/7]

static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore ( GrDirectContext *  context,
const FlutterBackingStoreConfig config,
const FlutterVulkanBackingStore vulkan 
)
static

Definition at line 1313 of file embedder.cc.

1316 {
1317#ifdef SHELL_ENABLE_VULKAN
1318 if (!vulkan->image) {
1319 FML_LOG(ERROR) << "Embedder supplied null Vulkan image.";
1320 return nullptr;
1321 }
1322 GrVkImageInfo image_info = {
1323 .fImage = reinterpret_cast<VkImage>(vulkan->image->image),
1324 .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
1325 .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1326 .fFormat = static_cast<VkFormat>(vulkan->image->format),
1327 .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1328 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1329 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1330 VK_IMAGE_USAGE_SAMPLED_BIT,
1331 .fSampleCount = 1,
1332 .fLevelCount = 1,
1333 };
1334 auto backend_texture = GrBackendTextures::MakeVk(
1335 config.size.width, config.size.height, image_info);
1336
1337 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
1338
1339 auto surface = SkSurfaces::WrapBackendTexture(
1340 context, // context
1341 backend_texture, // back-end texture
1342 kTopLeft_GrSurfaceOrigin, // surface origin
1343 1, // sample count
1345 static_cast<VkFormat>(vulkan->image->format)), // color type
1346 SkColorSpace::MakeSRGB(), // color space
1347 &surface_properties, // surface properties
1348 static_cast<SkSurfaces::TextureReleaseProc>(
1349 vulkan->destruction_callback), // release proc
1350 vulkan->user_data // release context
1351 );
1352
1353 if (!surface) {
1354 FML_LOG(ERROR) << "Could not wrap embedder supplied Vulkan render texture.";
1355 return nullptr;
1356 }
1357
1358 return surface;
1359#else
1360 return nullptr;
1361#endif
1362}

References flutter::GPUSurfaceVulkan::ColorTypeFromFormat(), context, FML_LOG, FlutterSize::height, FlutterBackingStoreConfig::size, surface, and FlutterSize::width.

◆ MakeViewportMetricsFromWindowMetrics()

static std::variant< flutter::ViewportMetrics, std::string > MakeViewportMetricsFromWindowMetrics ( const FlutterWindowMetricsEvent flutter_metrics)
static

Definition at line 1625 of file embedder.cc.

1626 {
1627 if (flutter_metrics == nullptr) {
1628 return "Invalid metrics handle.";
1629 }
1630
1632
1633 metrics.physical_width = SAFE_ACCESS(flutter_metrics, width, 0.0);
1634 metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
1635
1636 if (SAFE_ACCESS(flutter_metrics, has_constraints, false)) {
1638 flutter_metrics, min_width_constraint, metrics.physical_width);
1640 flutter_metrics, max_width_constraint, metrics.physical_width);
1642 flutter_metrics, min_height_constraint, metrics.physical_height);
1644 flutter_metrics, max_height_constraint, metrics.physical_height);
1645 } else {
1650 }
1651
1652 if (metrics.physical_width < metrics.physical_min_width_constraint ||
1656 return "Window metrics are invalid. Width and height must be within the "
1657 "specified constraints.";
1658 }
1659
1660 metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
1661 metrics.physical_view_inset_top =
1662 SAFE_ACCESS(flutter_metrics, physical_view_inset_top, 0.0);
1664 SAFE_ACCESS(flutter_metrics, physical_view_inset_right, 0.0);
1666 SAFE_ACCESS(flutter_metrics, physical_view_inset_bottom, 0.0);
1667 metrics.physical_view_inset_left =
1668 SAFE_ACCESS(flutter_metrics, physical_view_inset_left, 0.0);
1669 metrics.display_id = SAFE_ACCESS(flutter_metrics, display_id, 0);
1670
1671 if (metrics.device_pixel_ratio <= 0.0) {
1672 return "Device pixel ratio was invalid. It must be greater than zero.";
1673 }
1674
1675 if (metrics.physical_view_inset_top < 0 ||
1676 metrics.physical_view_inset_right < 0 ||
1677 metrics.physical_view_inset_bottom < 0 ||
1678 metrics.physical_view_inset_left < 0) {
1679 return "Physical view insets are invalid. They must be non-negative.";
1680 }
1681
1682 if (metrics.physical_view_inset_top > metrics.physical_height ||
1683 metrics.physical_view_inset_right > metrics.physical_width ||
1684 metrics.physical_view_inset_bottom > metrics.physical_height ||
1685 metrics.physical_view_inset_left > metrics.physical_width) {
1686 return "Physical view insets are invalid. They cannot be greater than "
1687 "physical height or width.";
1688 }
1689
1690 return metrics;
1691}

References flutter::ViewportMetrics::device_pixel_ratio, flutter::ViewportMetrics::display_id, height, flutter::ViewportMetrics::physical_height, flutter::ViewportMetrics::physical_max_height_constraint, flutter::ViewportMetrics::physical_max_width_constraint, flutter::ViewportMetrics::physical_min_height_constraint, flutter::ViewportMetrics::physical_min_width_constraint, flutter::ViewportMetrics::physical_view_inset_bottom, flutter::ViewportMetrics::physical_view_inset_left, flutter::ViewportMetrics::physical_view_inset_right, flutter::ViewportMetrics::physical_view_inset_top, flutter::ViewportMetrics::physical_width, SAFE_ACCESS, and width.

Referenced by FlutterEngineAddView(), and FlutterEngineSendWindowMetricsEvent().

◆ MapKeyEventDeviceType()

◆ MapKeyEventType()

static flutter::KeyEventType MapKeyEventType ( FlutterKeyEventType  event_kind)
inlinestatic

◆ PointerDataButtonsForLegacyEvent()

◆ PopulateAOTSnapshotMappingCallbacks()

void PopulateAOTSnapshotMappingCallbacks ( const FlutterProjectArgs args,
flutter::Settings settings 
)

Definition at line 1827 of file embedder.cc.

1829 { // NOLINT(google-runtime-references)
1830 // There are no ownership concerns here as all mappings are owned by the
1831 // embedder and not the engine.
1832 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
1833 return [mapping, size]() {
1834 return std::make_unique<fml::NonOwnedMapping>(mapping, size);
1835 };
1836 };
1837
1838 if (SAFE_ACCESS(args, aot_data, nullptr) != nullptr) {
1839 settings.vm_snapshot_data =
1840 make_mapping_callback(args->aot_data->vm_snapshot_data, 0);
1841
1842 settings.vm_snapshot_instr =
1843 make_mapping_callback(args->aot_data->vm_snapshot_instrs, 0);
1844
1845 settings.isolate_snapshot_data =
1846 make_mapping_callback(args->aot_data->vm_isolate_data, 0);
1847
1848 settings.isolate_snapshot_instr =
1849 make_mapping_callback(args->aot_data->vm_isolate_instrs, 0);
1850 }
1851
1852 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1853 settings.vm_snapshot_data = make_mapping_callback(
1854 args->vm_snapshot_data, SAFE_ACCESS(args, vm_snapshot_data_size, 0));
1855 }
1856
1857 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1858 settings.vm_snapshot_instr = make_mapping_callback(
1859 args->vm_snapshot_instructions,
1860 SAFE_ACCESS(args, vm_snapshot_instructions_size, 0));
1861 }
1862
1863 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1864 settings.isolate_snapshot_data =
1865 make_mapping_callback(args->isolate_snapshot_data,
1866 SAFE_ACCESS(args, isolate_snapshot_data_size, 0));
1867 }
1868
1869 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1870 settings.isolate_snapshot_instr = make_mapping_callback(
1871 args->isolate_snapshot_instructions,
1872 SAFE_ACCESS(args, isolate_snapshot_instructions_size, 0));
1873 }
1874}

References args, flutter::Settings::isolate_snapshot_data, flutter::Settings::isolate_snapshot_instr, SAFE_ACCESS, flutter::Settings::vm_snapshot_data, and flutter::Settings::vm_snapshot_instr.

Referenced by FlutterEngineInitialize().

◆ PopulateJITSnapshotMappingCallbacks()

void PopulateJITSnapshotMappingCallbacks ( const FlutterProjectArgs args,
flutter::Settings settings 
)

Definition at line 1784 of file embedder.cc.

1785 {
1786 auto make_mapping_callback = [](const char* path, bool executable) {
1787 return [path, executable]() {
1788 if (executable) {
1790 } else {
1792 }
1793 };
1794 };
1795
1796 // Users are allowed to specify only certain snapshots if they so desire.
1797 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1798 settings.vm_snapshot_data = make_mapping_callback(
1799 reinterpret_cast<const char*>(args->vm_snapshot_data), false);
1800 }
1801
1802 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1803 settings.vm_snapshot_instr = make_mapping_callback(
1804 reinterpret_cast<const char*>(args->vm_snapshot_instructions), true);
1805 }
1806
1807 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1808 settings.isolate_snapshot_data = make_mapping_callback(
1809 reinterpret_cast<const char*>(args->isolate_snapshot_data), false);
1810 }
1811
1812 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1813 settings.isolate_snapshot_instr = make_mapping_callback(
1814 reinterpret_cast<const char*>(args->isolate_snapshot_instructions),
1815 true);
1816 }
1817
1818#if !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
1819 settings.dart_library_sources_kernel = []() {
1820 return std::make_unique<fml::NonOwnedMapping>(kPlatformStrongDill,
1822 };
1823#endif // !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE ==
1824 // FLUTTER_RUNTIME_MODE_DEBUG)
1825}

References args, fml::FileMapping::CreateReadExecute(), fml::FileMapping::CreateReadOnly(), flutter::Settings::dart_library_sources_kernel, flutter::Settings::isolate_snapshot_data, flutter::Settings::isolate_snapshot_instr, kPlatformStrongDill, kPlatformStrongDillSize, SAFE_ACCESS, flutter::Settings::vm_snapshot_data, and flutter::Settings::vm_snapshot_instr.

Referenced by FlutterEngineInitialize().

◆ ToPointerDataChange()

◆ ToPointerDataKind()

◆ ToPointerDataSignalKind()

Variable Documentation

◆ kFlutterImplicitViewId

◆ kFlutterKeyDataChannel

const char* kFlutterKeyDataChannel = "flutter/keydata"

Definition at line 134 of file embedder.cc.

Referenced by FlutterEngineSendKeyEvent().

◆ kFlutterSemanticsCustomActionIdBatchEnd

const int32_t kFlutterSemanticsCustomActionIdBatchEnd = -1

FlutterSemanticsCustomAction ID used as a sentinel to signal the end of a batch of semantics custom action updates. This is unused if using FlutterUpdateSemanticsCallback2.

Definition at line 110 of file embedder.cc.

Referenced by CreateEmbedderSemanticsUpdateCallbackV1(), and flutter::testing::TEST_F().

◆ kFlutterSemanticsNodeIdBatchEnd

const int32_t kFlutterSemanticsNodeIdBatchEnd = -1

FlutterSemanticsNode ID used as a sentinel to signal the end of a batch of semantics node updates. This is unused if using FlutterUpdateSemanticsCallback2.

Definition at line 109 of file embedder.cc.

Referenced by CreateEmbedderSemanticsUpdateCallbackV1(), flutter::testing::TEST_F(), flutter::testing::TEST_F(), and flutter::testing::TEST_F().

◆ kPlatformStrongDill

const uint8_t kPlatformStrongDill[]
extern

◆ kPlatformStrongDillSize

const intptr_t kPlatformStrongDillSize
extern