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,
903 const FlutterOpenGLFramebuffer* framebuffer) {
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,
1152 const FlutterOpenGLFramebuffer* framebuffer) {
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_LoadELF2(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) {
2764 }
2766}
2767
2768// Returns the flutter::PointerData::SignalKind for the given
2769// FlutterPointerSignaKind.
2772 switch (kind) {
2781 }
2783}
2784
2785// Returns the buttons to synthesize for a PointerData from a
2786// FlutterPointerEvent with no type or buttons set.
2789 switch (change) {
2792 // These kinds of change must have a non-zero `buttons`, otherwise
2793 // gesture recognizers will ignore these events.
2803 return 0;
2804 }
2805 return 0;
2806}
2807
2810 const FlutterPointerEvent* pointers,
2811 size_t events_count) {
2812 if (engine == nullptr) {
2813 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2814 }
2815
2816 if (pointers == nullptr || events_count == 0) {
2817 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid pointer events.");
2818 }
2819
2820 auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
2821
2822 const FlutterPointerEvent* current = pointers;
2823
2824 for (size_t i = 0; i < events_count; ++i) {
2825 flutter::PointerData pointer_data;
2826 pointer_data.Clear();
2827 // this is currely in use only on android embedding.
2828 pointer_data.embedder_id = 0;
2829 pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
2830 pointer_data.change = ToPointerDataChange(
2831 SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
2832 pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
2833 pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
2834 // Delta will be generated in pointer_data_packet_converter.cc.
2835 pointer_data.physical_delta_x = 0.0;
2836 pointer_data.physical_delta_y = 0.0;
2837 pointer_data.device = SAFE_ACCESS(current, device, 0);
2838 // Pointer identifier will be generated in
2839 // pointer_data_packet_converter.cc.
2840 pointer_data.pointer_identifier = 0;
2841 pointer_data.signal_kind = ToPointerDataSignalKind(
2842 SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
2843 pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
2844 pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
2845 FlutterPointerDeviceKind device_kind =
2846 SAFE_ACCESS(current, device_kind, kFlutterPointerDeviceKindMouse);
2847 // For backwards compatibility with embedders written before the device
2848 // kind and buttons were exposed, if the device kind is not set treat it
2849 // as a mouse, with a synthesized primary button state based on the phase.
2850 if (device_kind == 0) {
2852 pointer_data.buttons =
2854
2855 } else {
2856 pointer_data.kind = ToPointerDataKind(device_kind);
2857 if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
2858 // For touch events, set the button internally rather than requiring
2859 // it at the API level, since it's a confusing construction to expose.
2860 if (pointer_data.change == flutter::PointerData::Change::kDown ||
2863 }
2864 } else {
2865 // Buttons use the same mask values, so pass them through directly.
2866 pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
2867 }
2868 }
2869 pointer_data.pan_x = SAFE_ACCESS(current, pan_x, 0.0);
2870 pointer_data.pan_y = SAFE_ACCESS(current, pan_y, 0.0);
2871 // Delta will be generated in pointer_data_packet_converter.cc.
2872 pointer_data.pan_delta_x = 0.0;
2873 pointer_data.pan_delta_y = 0.0;
2874 pointer_data.scale = SAFE_ACCESS(current, scale, 0.0);
2875 pointer_data.rotation = SAFE_ACCESS(current, rotation, 0.0);
2876 pointer_data.pressure = SAFE_ACCESS(current, pressure, 0.0);
2877 pointer_data.pressure_min = SAFE_ACCESS(current, pressure_min, 0.0);
2878 pointer_data.pressure_max = SAFE_ACCESS(current, pressure_max, 0.0);
2879 pointer_data.view_id =
2881 packet->SetPointerData(i, pointer_data);
2882 current = reinterpret_cast<const FlutterPointerEvent*>(
2883 reinterpret_cast<const uint8_t*>(current) + current->struct_size);
2884 }
2885
2886 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2887 ->DispatchPointerDataPacket(std::move(packet))
2888 ? kSuccess
2890 "Could not dispatch pointer events to the "
2891 "running Flutter application.");
2892}
2893
2895 FlutterKeyEventType event_kind) {
2896 switch (event_kind) {
2903 }
2905}
2906
2908 FlutterKeyEventDeviceType event_kind) {
2909 switch (event_kind) {
2920 }
2922}
2923
2924// Send a platform message to the framework.
2925//
2926// The `data_callback` will be invoked with `user_data`, and must not be empty.
2929 const char* channel,
2930 const uint8_t* data,
2931 size_t size,
2932 FlutterDataCallback data_callback,
2933 void* user_data) {
2934 FlutterEngineResult result;
2935
2936 FlutterPlatformMessageResponseHandle* response_handle;
2938 engine, data_callback, user_data, &response_handle);
2939 if (result != kSuccess) {
2940 return result;
2941 }
2942
2944 sizeof(FlutterPlatformMessage), // struct_size
2945 channel, // channel
2946 data, // message
2947 size, // message_size
2948 response_handle, // response_handle
2949 };
2950
2952 // Whether `SendPlatformMessage` succeeds or not, the response handle must be
2953 // released.
2954 FlutterEngineResult release_result =
2956 if (result != kSuccess) {
2957 return result;
2958 }
2959
2960 return release_result;
2961}
2962
2964 engine,
2965 const FlutterKeyEvent* event,
2967 void* user_data) {
2968 if (engine == nullptr) {
2969 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2970 }
2971
2972 if (event == nullptr) {
2973 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid key event.");
2974 }
2975
2976 const char* character = SAFE_ACCESS(event, character, nullptr);
2977
2978 flutter::KeyData key_data;
2979 key_data.Clear();
2980 key_data.timestamp = static_cast<uint64_t>(SAFE_ACCESS(event, timestamp, 0));
2981 key_data.type = MapKeyEventType(
2983 key_data.physical = SAFE_ACCESS(event, physical, 0);
2984 key_data.logical = SAFE_ACCESS(event, logical, 0);
2985 key_data.synthesized = SAFE_ACCESS(event, synthesized, false);
2987 event, device_type,
2989
2990 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data, character);
2991
2992 struct MessageData {
2994 void* user_data;
2995 };
2996
2997 MessageData* message_data =
2998 new MessageData{.callback = callback, .user_data = user_data};
2999
3000 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
3002 engine, kFlutterKeyDataChannel, packet->data().data(),
3003 packet->data().size(),
3004 [](const uint8_t* data, size_t size, void* user_data) {
3005 auto message_data = std::unique_ptr<MessageData>(
3006 reinterpret_cast<MessageData*>(user_data));
3007 if (message_data->callback == nullptr) {
3008 return;
3009 }
3010 bool handled = false;
3011 if (size == 1) {
3012 handled = *data != 0;
3013 }
3014 message_data->callback(handled, message_data->user_data);
3015 },
3016 message_data);
3017}
3018
3021 const FlutterPlatformMessage* flutter_message) {
3022 if (engine == nullptr) {
3023 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3024 }
3025
3026 if (flutter_message == nullptr) {
3027 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid message argument.");
3028 }
3029
3030 if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
3031 return LOG_EMBEDDER_ERROR(
3032 kInvalidArguments, "Message argument did not specify a valid channel.");
3033 }
3034
3035 size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
3036 const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
3037
3038 if (message_size != 0 && message_data == nullptr) {
3039 return LOG_EMBEDDER_ERROR(
3041 "Message size was non-zero but the message data was nullptr.");
3042 }
3043
3044 const FlutterPlatformMessageResponseHandle* response_handle =
3045 SAFE_ACCESS(flutter_message, response_handle, nullptr);
3046
3048 if (response_handle && response_handle->message) {
3049 response = response_handle->message->response();
3050 }
3051
3052 std::unique_ptr<flutter::PlatformMessage> message;
3053 if (message_size == 0) {
3054 message = std::make_unique<flutter::PlatformMessage>(
3055 flutter_message->channel, response);
3056 } else {
3057 message = std::make_unique<flutter::PlatformMessage>(
3058 flutter_message->channel,
3059 fml::MallocMapping::Copy(message_data, message_size), response);
3060 }
3061
3062 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3063 ->SendPlatformMessage(std::move(message))
3064 ? kSuccess
3066 "Could not send a message to the running "
3067 "Flutter application.");
3068}
3069
3072 FlutterDataCallback data_callback,
3073 void* user_data,
3074 FlutterPlatformMessageResponseHandle** response_out) {
3075 if (engine == nullptr) {
3076 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3077 }
3078
3079 if (data_callback == nullptr || response_out == nullptr) {
3080 return LOG_EMBEDDER_ERROR(
3081 kInvalidArguments, "Data callback or the response handle was invalid.");
3082 }
3083
3085 [user_data, data_callback](const uint8_t* data, size_t size) {
3086 data_callback(data, size, user_data);
3087 };
3088
3089 auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
3090 ->GetTaskRunners()
3091 .GetPlatformTaskRunner();
3092
3093 auto handle = new FlutterPlatformMessageResponseHandle();
3094
3095 handle->message = std::make_unique<flutter::PlatformMessage>(
3096 "", // The channel is empty and unused as the response handle is going
3097 // to referenced directly in the |FlutterEngineSendPlatformMessage|
3098 // with the container message discarded.
3099 fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
3100 std::move(platform_task_runner), response_callback));
3101 *response_out = handle;
3102 return kSuccess;
3103}
3104
3108 if (engine == nullptr) {
3109 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3110 }
3111
3112 if (response == nullptr) {
3113 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid response handle.");
3114 }
3115 delete response;
3116 return kSuccess;
3117}
3118
3119// Note: This can execute on any thread.
3123 const uint8_t* data,
3124 size_t data_length) {
3125 if (data_length != 0 && data == nullptr) {
3126 return LOG_EMBEDDER_ERROR(
3128 "Data size was non zero but the pointer to the data was null.");
3129 }
3130
3131 auto response = handle->message->response();
3132
3133 if (response) {
3134 if (data_length == 0) {
3135 response->CompleteEmpty();
3136 } else {
3137 response->Complete(std::make_unique<fml::DataMapping>(
3138 std::vector<uint8_t>({data, data + data_length})));
3139 }
3140 }
3141
3142 delete handle;
3143
3144 return kSuccess;
3145}
3146
3149 return kSuccess;
3150}
3151
3154 int64_t texture_identifier) {
3155 if (engine == nullptr) {
3156 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3157 }
3158
3159 if (texture_identifier == 0) {
3161 "Texture identifier was invalid.");
3162 }
3163 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
3164 texture_identifier)) {
3166 "Could not register the specified texture.");
3167 }
3168 return kSuccess;
3169}
3170
3173 int64_t texture_identifier) {
3174 if (engine == nullptr) {
3175 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
3176 }
3177
3178 if (texture_identifier == 0) {
3180 "Texture identifier was invalid.");
3181 }
3182
3183 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
3184 texture_identifier)) {
3186 "Could not un-register the specified texture.");
3187 }
3188
3189 return kSuccess;
3190}
3191
3194 int64_t texture_identifier) {
3195 if (engine == nullptr) {
3196 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3197 }
3198 if (texture_identifier == 0) {
3199 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid texture identifier.");
3200 }
3201 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3202 ->MarkTextureFrameAvailable(texture_identifier)) {
3203 return LOG_EMBEDDER_ERROR(
3205 "Could not mark the texture frame as being available.");
3206 }
3207 return kSuccess;
3208}
3209
3212 bool enabled) {
3213 if (engine == nullptr) {
3214 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3215 }
3216 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetSemanticsEnabled(
3217 enabled)) {
3219 "Could not update semantics state.");
3220 }
3221 return kSuccess;
3222}
3223
3227 if (engine == nullptr) {
3228 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3229 }
3230 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3231 ->SetAccessibilityFeatures(flags)) {
3233 "Could not update accessibility features.");
3234 }
3235 return kSuccess;
3236}
3237
3240 uint64_t node_id,
3242 const uint8_t* data,
3243 size_t data_length) {
3247 .node_id = node_id,
3248 .action = action,
3249 .data = data,
3250 .data_length = data_length};
3252}
3253
3256 const FlutterSendSemanticsActionInfo* info) {
3257 if (engine == nullptr) {
3258 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3259 }
3260 auto engine_action = static_cast<flutter::SemanticsAction>(info->action);
3261 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3263 info->view_id, info->node_id, engine_action,
3264 fml::MallocMapping::Copy(info->data, info->data_length))) {
3266 "Could not dispatch semantics action.");
3267 }
3268 return kSuccess;
3269}
3270
3272 engine,
3273 intptr_t baton,
3274 uint64_t frame_start_time_nanos,
3275 uint64_t frame_target_time_nanos) {
3276 if (engine == nullptr) {
3277 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3278 }
3279
3280 TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
3281
3282 auto start_time = fml::TimePoint::FromEpochDelta(
3283 fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
3284
3285 auto target_time = fml::TimePoint::FromEpochDelta(
3286 fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
3287
3288 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
3289 baton, start_time, target_time)) {
3290 return LOG_EMBEDDER_ERROR(
3292 "Could not notify the running engine instance of a Vsync event.");
3293 }
3294
3295 return kSuccess;
3296}
3297
3300 if (engine == nullptr) {
3301 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3302 }
3303
3304 TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
3305
3306 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
3307 ->ReloadSystemFonts()) {
3309 "Could not reload system fonts.");
3310 }
3311
3312 return kSuccess;
3313}
3314
3316 fml::tracing::TraceEvent0("flutter", name, /*flow_id_count=*/0,
3317 /*flow_ids=*/nullptr);
3318}
3319
3320void FlutterEngineTraceEventDurationEnd(const char* name) {
3322}
3323
3324void FlutterEngineTraceEventInstant(const char* name) {
3325 fml::tracing::TraceEventInstant0("flutter", name, /*flow_id_count=*/0,
3326 /*flow_ids=*/nullptr);
3327}
3328
3332 void* baton) {
3333 if (engine == nullptr) {
3334 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3335 }
3336
3337 if (callback == nullptr) {
3339 "Render thread callback was null.");
3340 }
3341
3342 auto task = [callback, baton]() { callback(baton); };
3343
3344 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3345 ->PostRenderThreadTask(task)
3346 ? kSuccess
3348 "Could not post the render thread task.");
3349}
3350
3351uint64_t FlutterEngineGetCurrentTime() {
3353}
3354
3356 engine,
3357 const FlutterTask* task) {
3358 if (engine == nullptr) {
3359 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3360 }
3361
3363 reinterpret_cast<intptr_t>(task->runner))) {
3364 // This task came too late, the embedder has already been destroyed.
3365 // This is not an error, just ignore the task.
3366 return kSuccess;
3367 }
3368
3369 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
3370 ? kSuccess
3372 "Could not run the specified task.");
3373}
3374
3376 engine,
3377 const rapidjson::Document& document,
3378 const std::string& channel_name) {
3379 if (channel_name.empty()) {
3380 return false;
3381 }
3382
3383 rapidjson::StringBuffer buffer;
3384 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
3385
3386 if (!document.Accept(writer)) {
3387 return false;
3388 }
3389
3390 const char* message = buffer.GetString();
3391
3392 if (message == nullptr || buffer.GetSize() == 0) {
3393 return false;
3394 }
3395
3396 auto platform_message = std::make_unique<flutter::PlatformMessage>(
3397 channel_name.c_str(), // channel
3399 buffer.GetSize()), // message
3400 nullptr // response
3401 );
3402
3403 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3404 ->SendPlatformMessage(std::move(platform_message));
3405}
3406
3408 engine,
3409 const FlutterLocale** locales,
3410 size_t locales_count) {
3411 if (engine == nullptr) {
3412 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3413 }
3414
3415 if (locales_count == 0) {
3416 return kSuccess;
3417 }
3418
3419 if (locales == nullptr) {
3420 return LOG_EMBEDDER_ERROR(kInvalidArguments, "No locales were specified.");
3421 }
3422
3423 rapidjson::Document document;
3424 auto& allocator = document.GetAllocator();
3425
3426 document.SetObject();
3427 document.AddMember("method", "setLocale", allocator);
3428
3429 rapidjson::Value args(rapidjson::kArrayType);
3430 args.Reserve(locales_count * 4, allocator);
3431 for (size_t i = 0; i < locales_count; ++i) {
3432 const FlutterLocale* locale = locales[i];
3433 const char* language_code_str = SAFE_ACCESS(locale, language_code, nullptr);
3434 if (language_code_str == nullptr || ::strlen(language_code_str) == 0) {
3435 return LOG_EMBEDDER_ERROR(
3437 "Language code is required but not present in FlutterLocale.");
3438 }
3439
3440 const char* country_code_str = SAFE_ACCESS(locale, country_code, "");
3441 const char* script_code_str = SAFE_ACCESS(locale, script_code, "");
3442 const char* variant_code_str = SAFE_ACCESS(locale, variant_code, "");
3443
3444 rapidjson::Value language_code, country_code, script_code, variant_code;
3445
3446 language_code.SetString(language_code_str, allocator);
3447 country_code.SetString(country_code_str ? country_code_str : "", allocator);
3448 script_code.SetString(script_code_str ? script_code_str : "", allocator);
3449 variant_code.SetString(variant_code_str ? variant_code_str : "", allocator);
3450
3451 // Required.
3452 args.PushBack(language_code, allocator);
3453 args.PushBack(country_code, allocator);
3454 args.PushBack(script_code, allocator);
3455 args.PushBack(variant_code, allocator);
3456 }
3457 document.AddMember("args", args, allocator);
3458
3459 return DispatchJSONPlatformMessage(engine, document, "flutter/localization")
3460 ? kSuccess
3462 "Could not send message to update locale of "
3463 "a running Flutter application.");
3464}
3465
3468}
3469
3473 const FlutterEngineDartObject* object) {
3474 if (engine == nullptr) {
3475 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3476 }
3477
3478 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->IsValid()) {
3479 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine not running.");
3480 }
3481
3482 if (port == ILLEGAL_PORT) {
3484 "Attempted to post to an illegal port.");
3485 }
3486
3487 if (object == nullptr) {
3489 "Invalid Dart object to post.");
3490 }
3491
3492 Dart_CObject dart_object = {};
3493 fml::ScopedCleanupClosure typed_data_finalizer;
3494
3495 switch (object->type) {
3497 dart_object.type = Dart_CObject_kNull;
3498 break;
3500 dart_object.type = Dart_CObject_kBool;
3501 dart_object.value.as_bool = object->bool_value;
3502 break;
3504 dart_object.type = Dart_CObject_kInt32;
3505 dart_object.value.as_int32 = object->int32_value;
3506 break;
3508 dart_object.type = Dart_CObject_kInt64;
3509 dart_object.value.as_int64 = object->int64_value;
3510 break;
3512 dart_object.type = Dart_CObject_kDouble;
3513 dart_object.value.as_double = object->double_value;
3514 break;
3516 if (object->string_value == nullptr) {
3518 "kFlutterEngineDartObjectTypeString must be "
3519 "a null terminated string but was null.");
3520 }
3521 dart_object.type = Dart_CObject_kString;
3522 dart_object.value.as_string = const_cast<char*>(object->string_value);
3523 break;
3525 auto* buffer = SAFE_ACCESS(object->buffer_value, buffer, nullptr);
3526 if (buffer == nullptr) {
3528 "kFlutterEngineDartObjectTypeBuffer must "
3529 "specify a buffer but found nullptr.");
3530 }
3531 auto buffer_size = SAFE_ACCESS(object->buffer_value, buffer_size, 0);
3532 auto callback =
3533 SAFE_ACCESS(object->buffer_value, buffer_collect_callback, nullptr);
3534 auto user_data = SAFE_ACCESS(object->buffer_value, user_data, nullptr);
3535
3536 // The user has provided a callback, let them manage the lifecycle of
3537 // the underlying data. If not, copy it out from the provided buffer.
3538
3539 if (callback == nullptr) {
3540 dart_object.type = Dart_CObject_kTypedData;
3541 dart_object.value.as_typed_data.type = Dart_TypedData_kUint8;
3542 dart_object.value.as_typed_data.length = buffer_size;
3543 dart_object.value.as_typed_data.values = buffer;
3544 } else {
3545 struct ExternalTypedDataPeer {
3546 void* user_data = nullptr;
3547 VoidCallback trampoline = nullptr;
3548 };
3549 auto peer = new ExternalTypedDataPeer();
3550 peer->user_data = user_data;
3551 peer->trampoline = callback;
3552 // This finalizer is set so that in case of failure of the
3553 // Dart_PostCObject below, we collect the peer. The embedder is still
3554 // responsible for collecting the buffer in case of non-kSuccess
3555 // returns from this method. This finalizer must be released in case
3556 // of kSuccess returns from this method.
3557 typed_data_finalizer.SetClosure([peer]() {
3558 // This is the tiny object we use as the peer to the Dart call so
3559 // that we can attach the a trampoline to the embedder supplied
3560 // callback. In case of error, we need to collect this object lest
3561 // we introduce a tiny leak.
3562 delete peer;
3563 });
3564 dart_object.type = Dart_CObject_kExternalTypedData;
3565 dart_object.value.as_external_typed_data.type = Dart_TypedData_kUint8;
3566 dart_object.value.as_external_typed_data.length = buffer_size;
3567 dart_object.value.as_external_typed_data.data = buffer;
3568 dart_object.value.as_external_typed_data.peer = peer;
3569 dart_object.value.as_external_typed_data.callback =
3570 +[](void* unused_isolate_callback_data, void* peer) {
3571 auto typed_peer = reinterpret_cast<ExternalTypedDataPeer*>(peer);
3572 typed_peer->trampoline(typed_peer->user_data);
3573 delete typed_peer;
3574 };
3575 }
3576 } break;
3577 default:
3578 return LOG_EMBEDDER_ERROR(
3580 "Invalid FlutterEngineDartObjectType type specified.");
3581 }
3582
3583 if (!Dart_PostCObject(port, &dart_object)) {
3585 "Could not post the object to the Dart VM.");
3586 }
3587
3588 // On a successful call, the VM takes ownership of and is responsible for
3589 // invoking the finalizer.
3590 typed_data_finalizer.Release();
3591 return kSuccess;
3592}
3593
3595 FLUTTER_API_SYMBOL(FlutterEngine) raw_engine) {
3596 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3597 if (engine == nullptr || !engine->IsValid()) {
3598 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine was invalid.");
3599 }
3600
3601 engine->GetShell().NotifyLowMemoryWarning();
3602
3603 rapidjson::Document document;
3604 auto& allocator = document.GetAllocator();
3605
3606 document.SetObject();
3607 document.AddMember("type", "memoryPressure", allocator);
3608
3609 return DispatchJSONPlatformMessage(raw_engine, document, "flutter/system")
3610 ? kSuccess
3613 "Could not dispatch the low memory notification message.");
3614}
3615
3619 void* user_data) {
3620 if (engine == nullptr) {
3621 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3622 }
3623
3624 if (callback == nullptr) {
3626 "Invalid native thread callback.");
3627 }
3628
3629 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3630 ->PostTaskOnEngineManagedNativeThreads(
3633 })
3634 ? kSuccess
3636 "Internal error while attempting to post "
3637 "tasks to all threads.");
3638}
3639
3640namespace {
3641static bool ValidDisplayConfiguration(const FlutterEngineDisplay* displays,
3642 size_t display_count) {
3643 std::set<FlutterEngineDisplayId> display_ids;
3644 for (size_t i = 0; i < display_count; i++) {
3645 if (displays[i].single_display && display_count != 1) {
3646 return false;
3647 }
3648 display_ids.insert(displays[i].display_id);
3649 }
3650
3651 return display_ids.size() == display_count;
3652}
3653} // namespace
3654
3657 const FlutterEngineDisplaysUpdateType update_type,
3658 const FlutterEngineDisplay* embedder_displays,
3659 size_t display_count) {
3660 if (raw_engine == nullptr) {
3661 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3662 }
3663
3664 if (!ValidDisplayConfiguration(embedder_displays, display_count)) {
3665 return LOG_EMBEDDER_ERROR(
3667 "Invalid FlutterEngineDisplay configuration specified.");
3668 }
3669
3670 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3671
3672 switch (update_type) {
3674 std::vector<std::unique_ptr<flutter::Display>> displays;
3675 const auto* display = embedder_displays;
3676 for (size_t i = 0; i < display_count; i++) {
3677 displays.push_back(std::make_unique<flutter::Display>(
3678 SAFE_ACCESS(display, display_id, i), //
3679 SAFE_ACCESS(display, refresh_rate, 0), //
3680 SAFE_ACCESS(display, width, 0), //
3681 SAFE_ACCESS(display, height, 0), //
3682 SAFE_ACCESS(display, device_pixel_ratio, 1)));
3683 display = reinterpret_cast<const FlutterEngineDisplay*>(
3684 reinterpret_cast<const uint8_t*>(display) + display->struct_size);
3685 }
3686 engine->GetShell().OnDisplayUpdates(std::move(displays));
3687 return kSuccess;
3688 }
3689 default:
3690 return LOG_EMBEDDER_ERROR(
3692 "Invalid FlutterEngineDisplaysUpdateType type specified.");
3693 }
3694}
3695
3697 engine) {
3698 if (engine == nullptr) {
3699 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3700 }
3701
3702 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->ScheduleFrame()
3703 ? kSuccess
3705 "Could not schedule frame.");
3706}
3707
3711 void* user_data) {
3712 if (engine == nullptr) {
3713 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3714 }
3715
3716 if (callback == nullptr) {
3718 "Next frame callback was null.");
3719 }
3720
3721 flutter::EmbedderEngine* embedder_engine =
3722 reinterpret_cast<flutter::EmbedderEngine*>(engine);
3723
3724 fml::WeakPtr<flutter::PlatformView> weak_platform_view =
3725 embedder_engine->GetShell().GetPlatformView();
3726
3727 if (!weak_platform_view) {
3729 "Platform view unavailable.");
3730 }
3731
3732 weak_platform_view->SetNextFrameCallback(
3734
3735 return kSuccess;
3736}
3737
3739 FlutterEngineProcTable* table) {
3740 if (!table) {
3741 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null table specified.");
3742 }
3743#define SET_PROC(member, function) \
3744 if (STRUCT_HAS_MEMBER(table, member)) { \
3745 table->member = &function; \
3746 }
3747
3748 SET_PROC(CreateAOTData, FlutterEngineCreateAOTData);
3749 SET_PROC(CollectAOTData, FlutterEngineCollectAOTData);
3752 SET_PROC(Initialize, FlutterEngineInitialize);
3753 SET_PROC(Deinitialize, FlutterEngineDeinitialize);
3754 SET_PROC(RunInitialized, FlutterEngineRunInitialized);
3755 SET_PROC(SendWindowMetricsEvent, FlutterEngineSendWindowMetricsEvent);
3756 SET_PROC(SendPointerEvent, FlutterEngineSendPointerEvent);
3757 SET_PROC(SendKeyEvent, FlutterEngineSendKeyEvent);
3758 SET_PROC(SendPlatformMessage, FlutterEngineSendPlatformMessage);
3759 SET_PROC(PlatformMessageCreateResponseHandle,
3761 SET_PROC(PlatformMessageReleaseResponseHandle,
3763 SET_PROC(SendPlatformMessageResponse,
3765 SET_PROC(RegisterExternalTexture, FlutterEngineRegisterExternalTexture);
3766 SET_PROC(UnregisterExternalTexture, FlutterEngineUnregisterExternalTexture);
3767 SET_PROC(MarkExternalTextureFrameAvailable,
3769 SET_PROC(UpdateSemanticsEnabled, FlutterEngineUpdateSemanticsEnabled);
3770 SET_PROC(UpdateAccessibilityFeatures,
3772 SET_PROC(DispatchSemanticsAction, FlutterEngineDispatchSemanticsAction);
3773 SET_PROC(SendSemanticsAction, FlutterEngineSendSemanticsAction);
3775 SET_PROC(ReloadSystemFonts, FlutterEngineReloadSystemFonts);
3776 SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin);
3777 SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd);
3778 SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant);
3779 SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask);
3782 SET_PROC(UpdateLocales, FlutterEngineUpdateLocales);
3783 SET_PROC(RunsAOTCompiledDartCode, FlutterEngineRunsAOTCompiledDartCode);
3784 SET_PROC(PostDartObject, FlutterEnginePostDartObject);
3785 SET_PROC(NotifyLowMemoryWarning, FlutterEngineNotifyLowMemoryWarning);
3786 SET_PROC(PostCallbackOnAllNativeThreads,
3788 SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate);
3789 SET_PROC(ScheduleFrame, FlutterEngineScheduleFrame);
3790 SET_PROC(SetNextFrameCallback, FlutterEngineSetNextFrameCallback);
3792 SET_PROC(RemoveView, FlutterEngineRemoveView);
3793 SET_PROC(SendViewFocusEvent, FlutterEngineSendViewFocusEvent);
3794#undef SET_PROC
3795
3796 return kSuccess;
3797}
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:52
fml::closure Release()
Definition closure.h:58
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:3325
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:2928
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:3193
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:3356
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:3272
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:3153
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:3408
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:3739
static bool DispatchJSONPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const rapidjson::Document &document, const std::string &channel_name)
Definition embedder.cc:3376
FlutterEngineResult FlutterEngineScheduleFrame(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Schedule a new frame to redraw the content.
Definition embedder.cc:3697
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:3316
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:2700
flutter::PointerData::SignalKind ToPointerDataSignalKind(FlutterPointerSignalKind kind)
Definition embedder.cc:2771
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:3352
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:3709
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:3148
#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:3330
static flutter::KeyEventDeviceType MapKeyEventDeviceType(FlutterKeyEventDeviceType event_kind)
Definition embedder.cc:2908
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:3239
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:3471
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:3617
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:3225
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:3071
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:3656
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition embedder.cc:3020
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition embedder.cc:3467
FlutterEngineResult FlutterEngineReloadSystemFonts(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Reloads the system fonts in engine.
Definition embedder.cc:3299
static flutter::KeyEventType MapKeyEventType(FlutterKeyEventType event_kind)
Definition embedder.cc:2895
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:2809
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:3255
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:3595
FlutterEngineResult FlutterEngineUnregisterExternalTexture(FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
Unregister a previous texture registration.
Definition embedder.cc:3172
FlutterEngineResult FlutterEngineUpdateSemanticsEnabled(FLUTTER_API_SYMBOL(FlutterEngine) engine, bool enabled)
Enable or disable accessibility semantics.
Definition embedder.cc:3211
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:2964
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:3321
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:3121
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:2788
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:3106
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:1390
@ kFlutterKeyEventDeviceTypeKeyboard
Definition embedder.h:1391
@ kFlutterKeyEventDeviceTypeDirectionalPad
Definition embedder.h:1392
@ kFlutterKeyEventDeviceTypeHdmi
Definition embedder.h:1395
@ kFlutterKeyEventDeviceTypeJoystick
Definition embedder.h:1394
@ kFlutterKeyEventDeviceTypeGamepad
Definition embedder.h:1393
void(* FlutterUpdateSemanticsCustomActionCallback)(const FlutterSemanticsCustomAction *, void *)
Definition embedder.h:1854
void(* FlutterUpdateSemanticsCallback)(const FlutterSemanticsUpdate *, void *)
Definition embedder.h:1858
FlutterViewFocusState
Represents the focus state of a given [FlutterView].
Definition embedder.h:1219
@ kFlutterEngineAOTDataSourceTypeElfPath
Definition embedder.h:2466
FlutterViewFocusDirection
Definition embedder.h:1200
struct _FlutterPlatformMessageResponseHandle FlutterPlatformMessageResponseHandle
Definition embedder.h:1469
@ 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:1491
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:2461
@ kFlutterEngineDartObjectTypeString
Definition embedder.h:2374
@ kFlutterEngineDartObjectTypeBool
Definition embedder.h:2370
@ kFlutterEngineDartObjectTypeDouble
Definition embedder.h:2373
@ kFlutterEngineDartObjectTypeInt32
Definition embedder.h:2371
@ kFlutterEngineDartObjectTypeBuffer
Definition embedder.h:2377
@ kFlutterEngineDartObjectTypeInt64
Definition embedder.h:2372
@ kFlutterEngineDartObjectTypeNull
Definition embedder.h:2369
void(* FlutterLogMessageCallback)(const char *, const char *, void *)
Definition embedder.h:2486
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:2442
FlutterPointerSignalKind
The type of a pointer signal.
Definition embedder.h:1329
@ kFlutterPointerSignalKindScale
Definition embedder.h:1333
@ kFlutterPointerSignalKindScrollInertiaCancel
Definition embedder.h:1332
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1331
@ kFlutterPointerSignalKindNone
Definition embedder.h:1330
void(* FlutterUpdateSemanticsNodeCallback)(const FlutterSemanticsNode *, void *)
Definition embedder.h:1850
void(* VoidCallback)(void *)
Definition embedder.h:416
FlutterEngineDisplaysUpdateType
Definition embedder.h:2356
@ kFlutterEngineDisplaysUpdateTypeStartup
Definition embedder.h:2362
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:1465
int64_t FlutterViewId
Definition embedder.h:393
FlutterKeyEventType
Definition embedder.h:1384
@ kFlutterKeyEventTypeDown
Definition embedder.h:1386
@ kFlutterKeyEventTypeUp
Definition embedder.h:1385
@ kFlutterKeyEventTypeRepeat
Definition embedder.h:1387
void(* FlutterUpdateSemanticsCallback2)(const FlutterSemanticsUpdate2 *, void *)
Definition embedder.h:1862
int64_t FlutterEngineDartPort
Definition embedder.h:2366
@ kFlutterOpenGLTargetTypeFramebuffer
Definition embedder.h:424
@ kFlutterOpenGLTargetTypeSurface
Definition embedder.h:427
@ kFlutterOpenGLTargetTypeTexture
Definition embedder.h:421
@ kFlutterBackingStoreTypeSoftware2
Definition embedder.h:2098
@ kFlutterBackingStoreTypeMetal
Specifies a Metal backing store. This is backed by a Metal texture.
Definition embedder.h:2093
@ kFlutterBackingStoreTypeVulkan
Specifies a Vulkan backing store. This is backed by a Vulkan VkImage.
Definition embedder.h:2095
@ kFlutterBackingStoreTypeSoftware
Specified an software allocation for Flutter to render into using the CPU.
Definition embedder.h:2091
@ kFlutterBackingStoreTypeOpenGL
Definition embedder.h:2089
#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
@ 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
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:2131
FlutterVulkanBackingStore vulkan
Definition embedder.h:2123
FlutterMetalBackingStore metal
Definition embedder.h:2121
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:2109
FlutterOpenGLBackingStore open_gl
The description of the OpenGL backing store.
Definition embedder.h:2115
FlutterSoftwareBackingStore software
The description of the software backing store.
Definition embedder.h:2117
FlutterSoftwareBackingStore2 software2
The description of the software backing store.
Definition embedder.h:2119
size_t struct_size
The size of this struct. Must be sizeof(FlutterBackingStore).
Definition embedder.h:2103
An update to whether a message channel has a listener set or not.
Definition embedder.h:1867
FlutterBackingStoreCreateCallback create_backing_store_callback
Definition embedder.h:2251
FlutterBackingStoreCollectCallback collect_backing_store_callback
Definition embedder.h:2256
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:2472
const char * elf_path
Absolute path to an ELF library file.
Definition embedder.h:2475
FlutterEngineDartObjectType type
Definition embedder.h:2425
const char * string_value
Definition embedder.h:2434
const FlutterEngineDartBuffer * buffer_value
Definition embedder.h:2435
Function-pointer-based versions of the APIs above.
Definition embedder.h:3746
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:2185
FlutterMetalTexture texture
Definition embedder.h:2012
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:1961
FlutterOpenGLTexture texture
A texture for Flutter to render into.
Definition embedder.h:1955
FlutterOpenGLTargetType type
Definition embedder.h:1952
FlutterOpenGLFramebuffer framebuffer
Definition embedder.h:1958
uint32_t name
The name of the framebuffer.
Definition embedder.h:551
VoidCallback destruction_callback
Definition embedder.h:558
void * user_data
User data to be returned on the invocation of the destruction callback.
Definition embedder.h:554
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:1475
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition embedder.h:1338
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:1826
size_t nodes_count
The number of semantics node updates.
Definition embedder.h:1824
size_t custom_actions_count
The number of semantics custom action updates.
Definition embedder.h:1828
FlutterSemanticsCustomAction * custom_actions
Array of semantics custom actions. Has length custom_actions_count.
Definition embedder.h:1830
FlutterViewId view_id
The ID of the view that includes the node.
Definition embedder.h:2816
FlutterSemanticsAction action
The semantics action.
Definition embedder.h:2822
size_t data_length
The data length.
Definition embedder.h:2828
uint64_t node_id
The semantics node identifier.
Definition embedder.h:2819
const uint8_t * data
Data associated with the action.
Definition embedder.h:2825
double height
Definition embedder.h:636
double width
Definition embedder.h:635
VoidCallback destruction_callback
Definition embedder.h:1998
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1989
FlutterSoftwarePixelFormat pixel_format
Definition embedder.h:2002
VoidCallback destruction_callback
Definition embedder.h:1979
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1970
SoftwareSurfacePresentCallback surface_present_callback
Definition embedder.h:1034
FlutterTaskRunner runner
Definition embedder.h:1887
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:921
LoadAction load_action
Definition formats.h:922
std::shared_ptr< Texture > texture
Definition formats.h:920
StoreAction store_action
Definition formats.h:923
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 3148 of file embedder.cc.

3148 {
3150 return kSuccess;
3151}

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 3376 of file embedder.cc.

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

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_LoadELF2(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 3239 of file embedder.cc.

3244 {
3248 .node_id = node_id,
3249 .action = action,
3250 .data = data,
3251 .data_length = data_length};
3253}

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 3352 of file embedder.cc.

3352 {
3354}

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 3739 of file embedder.cc.

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

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 3193 of file embedder.cc.

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

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 3656 of file embedder.cc.

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

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 3595 of file embedder.cc.

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

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 3272 of file embedder.cc.

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

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 3617 of file embedder.cc.

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

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 3471 of file embedder.cc.

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

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 3330 of file embedder.cc.

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

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 3153 of file embedder.cc.

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

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 3299 of file embedder.cc.

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

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 3467 of file embedder.cc.

3467 {
3469}

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 3356 of file embedder.cc.

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

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 3697 of file embedder.cc.

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

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 2964 of file embedder.cc.

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

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 3020 of file embedder.cc.

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

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 3121 of file embedder.cc.

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

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 2809 of file embedder.cc.

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

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(), 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 3255 of file embedder.cc.

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

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 3709 of file embedder.cc.

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

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 3316 of file embedder.cc.

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

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 3321 of file embedder.cc.

3321 {
3323}

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 3325 of file embedder.cc.

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

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 3172 of file embedder.cc.

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

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 3225 of file embedder.cc.

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

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 3408 of file embedder.cc.

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

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 3211 of file embedder.cc.

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

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 3071 of file embedder.cc.

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

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 3106 of file embedder.cc.

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

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 2928 of file embedder.cc.

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

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(), FlutterOpenGLFramebuffer::destruction_callback, impeller::TextureDescriptor::format, format, 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, FlutterOpenGLFramebuffer::name, 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, FlutterOpenGLFramebuffer::target, impeller::Attachment::texture, impeller::TextureDescriptor::type, impeller::TextureDescriptor::usage, user_data, FlutterOpenGLFramebuffer::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, FlutterOpenGLFramebuffer::destruction_callback, FML_LOG, FlutterSize::height, FlutterOpenGLFramebuffer::name, FlutterBackingStoreConfig::size, surface, FlutterOpenGLFramebuffer::target, FlutterOpenGLFramebuffer::user_data, 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