Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Typedefs | Functions | Variables
embedder.cc File Reference
#include <cstring>
#include <iostream>
#include <memory>
#include <set>
#include <string>
#include <vector>
#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/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/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)
 
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)
 
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)
 
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)
 
static sk_sp< SkSurfaceMakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLTexture *texture)
 
static sk_sp< SkSurfaceMakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLFramebuffer *framebuffer)
 
static sk_sp< SkSurfaceMakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterSoftwareBackingStore *software)
 
static sk_sp< SkSurfaceMakeSkSurfaceFromBackingStore (GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterSoftwareBackingStore2 *software)
 
static sk_sp< SkSurfaceMakeSkSurfaceFromBackingStore (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< SkSurfaceMakeSkSurfaceFromBackingStore (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)
 
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 std::pair< std::unique_ptr< flutter::EmbedderExternalViewEmbedder >, bool > 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.
 
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.
 
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 engine 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 31 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 152 of file embedder.cc.

154 {
155 if (config->type != kOpenGL) {
156 return false;
157 }
158
159 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
160
161 if (!SAFE_EXISTS(open_gl_config, make_current) ||
162 !SAFE_EXISTS(open_gl_config, clear_current) ||
163 !SAFE_EXISTS_ONE_OF(open_gl_config, fbo_callback,
164 fbo_with_frame_info_callback) ||
165 !SAFE_EXISTS_ONE_OF(open_gl_config, present, present_with_info)) {
166 return false;
167 }
168
169 return true;
170}
171
172static bool IsSoftwareRendererConfigValid(const FlutterRendererConfig* config) {
173 if (config->type != kSoftware) {
174 return false;
175 }
176
177 const FlutterSoftwareRendererConfig* software_config = &config->software;
178
179 if (SAFE_ACCESS(software_config, surface_present_callback, nullptr) ==
180 nullptr) {
181 return false;
182 }
183
184 return true;
185}
186
187static bool IsMetalRendererConfigValid(const FlutterRendererConfig* config) {
188 if (config->type != kMetal) {
189 return false;
190 }
191
192 const FlutterMetalRendererConfig* metal_config = &config->metal;
193
194 bool device = SAFE_ACCESS(metal_config, device, nullptr);
195 bool command_queue =
196 SAFE_ACCESS(metal_config, present_command_queue, nullptr);
197
198 bool present = SAFE_ACCESS(metal_config, present_drawable_callback, nullptr);
199 bool get_texture =
200 SAFE_ACCESS(metal_config, get_next_drawable_callback, nullptr);
201
202 return device && command_queue && present && get_texture;
203}
204
205static bool IsVulkanRendererConfigValid(const FlutterRendererConfig* config) {
206 if (config->type != kVulkan) {
207 return false;
208 }
209
210 const FlutterVulkanRendererConfig* vulkan_config = &config->vulkan;
211
212 if (!SAFE_EXISTS(vulkan_config, instance) ||
213 !SAFE_EXISTS(vulkan_config, physical_device) ||
214 !SAFE_EXISTS(vulkan_config, device) ||
215 !SAFE_EXISTS(vulkan_config, queue) ||
216 !SAFE_EXISTS(vulkan_config, get_instance_proc_address_callback) ||
217 !SAFE_EXISTS(vulkan_config, get_next_image_callback) ||
218 !SAFE_EXISTS(vulkan_config, present_image_callback)) {
219 return false;
220 }
221
222 return true;
223}
224
225static bool IsRendererValid(const FlutterRendererConfig* config) {
226 if (config == nullptr) {
227 return false;
228 }
229
230 switch (config->type) {
231 case kOpenGL:
232 return IsOpenGLRendererConfigValid(config);
233 case kSoftware:
234 return IsSoftwareRendererConfigValid(config);
235 case kMetal:
236 return IsMetalRendererConfigValid(config);
237 case kVulkan:
238 return IsVulkanRendererConfigValid(config);
239 default:
240 return false;
241 }
242
243 return false;
244}
245
246#if FML_OS_LINUX || FML_OS_WIN
247static void* DefaultGLProcResolver(const char* name) {
248 static fml::RefPtr<fml::NativeLibrary> proc_library =
249#if FML_OS_LINUX
251#elif FML_OS_WIN // FML_OS_LINUX
252 fml::NativeLibrary::Create("opengl32.dll");
253#endif // FML_OS_WIN
254 return static_cast<void*>(
255 const_cast<uint8_t*>(proc_library->ResolveSymbol(name)));
256}
257#endif // FML_OS_LINUX || FML_OS_WIN
258
259#ifdef SHELL_ENABLE_GL
260// Auxiliary function used to translate rectangles of type SkIRect to
261// FlutterRect.
262static FlutterRect SkIRectToFlutterRect(const SkIRect sk_rect) {
263 FlutterRect flutter_rect = {static_cast<double>(sk_rect.fLeft),
264 static_cast<double>(sk_rect.fTop),
265 static_cast<double>(sk_rect.fRight),
266 static_cast<double>(sk_rect.fBottom)};
267 return flutter_rect;
268}
269
270// Auxiliary function used to translate rectangles of type FlutterRect to
271// SkIRect.
272static const SkIRect FlutterRectToSkIRect(FlutterRect flutter_rect) {
273 SkIRect rect = {static_cast<int32_t>(flutter_rect.left),
274 static_cast<int32_t>(flutter_rect.top),
275 static_cast<int32_t>(flutter_rect.right),
276 static_cast<int32_t>(flutter_rect.bottom)};
277 return rect;
278}
279#endif
280
283 const FlutterRendererConfig* config,
284 void* user_data,
286 platform_dispatch_table,
287 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
288 external_view_embedder,
289 bool enable_impeller) {
290#ifdef SHELL_ENABLE_GL
291 if (config->type != kOpenGL) {
292 return nullptr;
293 }
294
295 auto gl_make_current = [ptr = config->open_gl.make_current,
296 user_data]() -> bool { return ptr(user_data); };
297
298 auto gl_clear_current = [ptr = config->open_gl.clear_current,
299 user_data]() -> bool { return ptr(user_data); };
300
301 auto gl_present =
302 [present = config->open_gl.present,
303 present_with_info = config->open_gl.present_with_info,
304 user_data](flutter::GLPresentInfo gl_present_info) -> bool {
305 if (present) {
306 return present(user_data);
307 } else {
308 // Format the frame and buffer damages accordingly. Note that, since the
309 // current compute damage algorithm only returns one rectangle for damage
310 // we are assuming the number of rectangles provided in frame and buffer
311 // damage are always 1. Once the function that computes damage implements
312 // support for multiple damage rectangles, GLPresentInfo should also
313 // contain the number of damage rectangles.
314
315 std::optional<FlutterRect> frame_damage_rect;
316 if (gl_present_info.frame_damage) {
317 frame_damage_rect =
318 SkIRectToFlutterRect(*(gl_present_info.frame_damage));
319 }
320 std::optional<FlutterRect> buffer_damage_rect;
321 if (gl_present_info.buffer_damage) {
322 buffer_damage_rect =
323 SkIRectToFlutterRect(*(gl_present_info.buffer_damage));
324 }
325
326 FlutterDamage frame_damage{
327 .struct_size = sizeof(FlutterDamage),
328 .num_rects = frame_damage_rect ? size_t{1} : size_t{0},
329 .damage = frame_damage_rect ? &frame_damage_rect.value() : nullptr,
330 };
331 FlutterDamage buffer_damage{
332 .struct_size = sizeof(FlutterDamage),
333 .num_rects = buffer_damage_rect ? size_t{1} : size_t{0},
334 .damage = buffer_damage_rect ? &buffer_damage_rect.value() : nullptr,
335 };
336
337 // Construct the present information concerning the frame being rendered.
338 FlutterPresentInfo present_info = {
340 .fbo_id = gl_present_info.fbo_id,
341 .frame_damage = frame_damage,
342 .buffer_damage = buffer_damage,
343 };
344
345 return present_with_info(user_data, &present_info);
346 }
347 };
348
349 auto gl_fbo_callback =
350 [fbo_callback = config->open_gl.fbo_callback,
351 fbo_with_frame_info_callback =
353 user_data](flutter::GLFrameInfo gl_frame_info) -> intptr_t {
354 if (fbo_callback) {
355 return fbo_callback(user_data);
356 } else {
357 FlutterFrameInfo frame_info = {};
358 frame_info.struct_size = sizeof(FlutterFrameInfo);
359 frame_info.size = {gl_frame_info.width, gl_frame_info.height};
360 return fbo_with_frame_info_callback(user_data, &frame_info);
361 }
362 };
363
364 auto gl_populate_existing_damage =
365 [populate_existing_damage = config->open_gl.populate_existing_damage,
366 user_data](intptr_t id) -> flutter::GLFBOInfo {
367 // If no populate_existing_damage was provided, disable partial
368 // repaint.
369 if (!populate_existing_damage) {
370 return flutter::GLFBOInfo{
371 .fbo_id = static_cast<uint32_t>(id),
372 .existing_damage = std::nullopt,
373 };
374 }
375
376 // Given the FBO's ID, get its existing damage.
377 FlutterDamage existing_damage;
378 populate_existing_damage(user_data, id, &existing_damage);
379
380 std::optional<SkIRect> existing_damage_rect = std::nullopt;
381
382 // Verify that at least one damage rectangle was provided.
383 if (existing_damage.num_rects <= 0 || existing_damage.damage == nullptr) {
384 FML_LOG(INFO) << "No damage was provided. Forcing full repaint.";
385 } else {
386 existing_damage_rect = SkIRect::MakeEmpty();
387 for (size_t i = 0; i < existing_damage.num_rects; i++) {
388 existing_damage_rect->join(
389 FlutterRectToSkIRect(existing_damage.damage[i]));
390 }
391 }
392
393 // Pass the information about this FBO to the rendering backend.
394 return flutter::GLFBOInfo{
395 .fbo_id = static_cast<uint32_t>(id),
396 .existing_damage = existing_damage_rect,
397 };
398 };
399
400 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
401 std::function<bool()> gl_make_resource_current_callback = nullptr;
402 if (SAFE_ACCESS(open_gl_config, make_resource_current, nullptr) != nullptr) {
403 gl_make_resource_current_callback =
404 [ptr = config->open_gl.make_resource_current, user_data]() {
405 return ptr(user_data);
406 };
407 }
408
409 std::function<SkMatrix(void)> gl_surface_transformation_callback = nullptr;
410 if (SAFE_ACCESS(open_gl_config, surface_transformation, nullptr) != nullptr) {
411 gl_surface_transformation_callback =
412 [ptr = config->open_gl.surface_transformation, user_data]() {
413 FlutterTransformation transformation = ptr(user_data);
414 return SkMatrix::MakeAll(transformation.scaleX, //
415 transformation.skewX, //
416 transformation.transX, //
417 transformation.skewY, //
418 transformation.scaleY, //
419 transformation.transY, //
420 transformation.pers0, //
421 transformation.pers1, //
422 transformation.pers2 //
423 );
424 };
425
426 // If there is an external view embedder, ask it to apply the surface
427 // transformation to its surfaces as well.
428 if (external_view_embedder) {
429 external_view_embedder->SetSurfaceTransformationCallback(
430 gl_surface_transformation_callback);
431 }
432 }
433
434 flutter::GPUSurfaceGLDelegate::GLProcResolver gl_proc_resolver = nullptr;
435 if (SAFE_ACCESS(open_gl_config, gl_proc_resolver, nullptr) != nullptr) {
436 gl_proc_resolver = [ptr = config->open_gl.gl_proc_resolver,
437 user_data](const char* gl_proc_name) {
438 return ptr(user_data, gl_proc_name);
439 };
440 } else {
441#if FML_OS_LINUX || FML_OS_WIN
442 gl_proc_resolver = DefaultGLProcResolver;
443#endif
444 }
445
446 bool fbo_reset_after_present =
447 SAFE_ACCESS(open_gl_config, fbo_reset_after_present, false);
448
450 gl_make_current, // gl_make_current_callback
451 gl_clear_current, // gl_clear_current_callback
452 gl_present, // gl_present_callback
453 gl_fbo_callback, // gl_fbo_callback
454 gl_make_resource_current_callback, // gl_make_resource_current_callback
455 gl_surface_transformation_callback, // gl_surface_transformation_callback
456 gl_proc_resolver, // gl_proc_resolver
457 gl_populate_existing_damage, // gl_populate_existing_damage
458 };
459
460 return fml::MakeCopyable(
461 [gl_dispatch_table, fbo_reset_after_present, platform_dispatch_table,
462 enable_impeller,
463 external_view_embedder =
464 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
465 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
466 std::move(external_view_embedder);
467 if (enable_impeller) {
468 return std::make_unique<flutter::PlatformViewEmbedder>(
469 shell, // delegate
470 shell.GetTaskRunners(), // task runners
471 std::make_unique<flutter::EmbedderSurfaceGLImpeller>(
472 gl_dispatch_table, fbo_reset_after_present,
473 view_embedder), // embedder_surface
474 platform_dispatch_table, // embedder platform dispatch table
475 view_embedder // external view embedder
476 );
477 }
478 return std::make_unique<flutter::PlatformViewEmbedder>(
479 shell, // delegate
480 shell.GetTaskRunners(), // task runners
481 std::make_unique<flutter::EmbedderSurfaceGL>(
482 gl_dispatch_table, fbo_reset_after_present,
483 view_embedder), // embedder_surface
484 platform_dispatch_table, // embedder platform dispatch table
485 view_embedder // external view embedder
486 );
487 });
488#else
489 return nullptr;
490#endif
491}
492
495 const FlutterRendererConfig* config,
496 void* user_data,
498 platform_dispatch_table,
499 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
500 external_view_embedder,
501 bool enable_impeller) {
502 if (config->type != kMetal) {
503 return nullptr;
504 }
505
506#ifdef SHELL_ENABLE_METAL
507 std::function<bool(flutter::GPUMTLTextureInfo texture)> metal_present =
508 [ptr = config->metal.present_drawable_callback,
510 FlutterMetalTexture embedder_texture;
511 embedder_texture.struct_size = sizeof(FlutterMetalTexture);
512 embedder_texture.texture = texture.texture;
513 embedder_texture.texture_id = texture.texture_id;
514 embedder_texture.user_data = texture.destruction_context;
515 embedder_texture.destruction_callback = texture.destruction_callback;
516 return ptr(user_data, &embedder_texture);
517 };
518 auto metal_get_texture =
519 [ptr = config->metal.get_next_drawable_callback,
520 user_data](const SkISize& frame_size) -> flutter::GPUMTLTextureInfo {
521 FlutterFrameInfo frame_info = {};
522 frame_info.struct_size = sizeof(FlutterFrameInfo);
523 frame_info.size = {static_cast<uint32_t>(frame_size.width()),
524 static_cast<uint32_t>(frame_size.height())};
525 flutter::GPUMTLTextureInfo texture_info;
526
527 FlutterMetalTexture metal_texture = ptr(user_data, &frame_info);
528 texture_info.texture_id = metal_texture.texture_id;
529 texture_info.texture = metal_texture.texture;
530 texture_info.destruction_callback = metal_texture.destruction_callback;
531 texture_info.destruction_context = metal_texture.user_data;
532 return texture_info;
533 };
534
535 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
536 std::move(external_view_embedder);
537
538 std::unique_ptr<flutter::EmbedderSurface> embedder_surface;
539
540 if (enable_impeller) {
542 metal_dispatch_table = {
543 .present = metal_present,
544 .get_texture = metal_get_texture,
545 };
546 embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetalImpeller>(
547 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
550 metal_dispatch_table, view_embedder);
551 } else {
553 .present = metal_present,
554 .get_texture = metal_get_texture,
555 };
556 embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetal>(
557 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
560 metal_dispatch_table, view_embedder);
561 }
562
563 // The static leak checker gets confused by the use of fml::MakeCopyable.
564 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
565 return fml::MakeCopyable(
566 [embedder_surface = std::move(embedder_surface), platform_dispatch_table,
567 external_view_embedder = view_embedder](flutter::Shell& shell) mutable {
568 return std::make_unique<flutter::PlatformViewEmbedder>(
569 shell, // delegate
570 shell.GetTaskRunners(), // task runners
571 std::move(embedder_surface), // embedder surface
572 platform_dispatch_table, // platform dispatch table
573 std::move(external_view_embedder) // external view embedder
574 );
575 });
576#else
577 return nullptr;
578#endif
579}
580
583 const FlutterRendererConfig* config,
584 void* user_data,
586 platform_dispatch_table,
587 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
588 external_view_embedder) {
589 if (config->type != kVulkan) {
590 return nullptr;
591 }
592
593#ifdef SHELL_ENABLE_VULKAN
594 std::function<void*(VkInstance, const char*)>
595 vulkan_get_instance_proc_address =
597 VkInstance instance, const char* proc_name) -> void* {
598 return ptr(user_data, instance, proc_name);
599 };
600
601 auto vulkan_get_next_image =
602 [ptr = config->vulkan.get_next_image_callback,
603 user_data](const SkISize& frame_size) -> FlutterVulkanImage {
604 FlutterFrameInfo frame_info = {
605 .struct_size = sizeof(FlutterFrameInfo),
606 .size = {static_cast<uint32_t>(frame_size.width()),
607 static_cast<uint32_t>(frame_size.height())},
608 };
609
610 return ptr(user_data, &frame_info);
611 };
612
613 auto vulkan_present_image_callback =
614 [ptr = config->vulkan.present_image_callback, user_data](
615 VkImage image, VkFormat format) -> bool {
616 FlutterVulkanImage image_desc = {
618 .image = reinterpret_cast<uint64_t>(image),
619 .format = static_cast<uint32_t>(format),
620 };
621 return ptr(user_data, &image_desc);
622 };
623
624 auto vk_instance = static_cast<VkInstance>(config->vulkan.instance);
625 auto proc_addr =
626 vulkan_get_instance_proc_address(vk_instance, "vkGetInstanceProcAddr");
627
630 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
631 .get_next_image = vulkan_get_next_image,
632 .present_image = vulkan_present_image_callback,
633 };
634
635 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
636 std::move(external_view_embedder);
637
638 std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
639 std::make_unique<flutter::EmbedderSurfaceVulkan>(
640 config->vulkan.version, vk_instance,
645 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
646 static_cast<VkDevice>(config->vulkan.device),
648 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
649 view_embedder);
650
651 return fml::MakeCopyable(
652 [embedder_surface = std::move(embedder_surface), platform_dispatch_table,
653 external_view_embedder =
654 std::move(view_embedder)](flutter::Shell& shell) mutable {
655 return std::make_unique<flutter::PlatformViewEmbedder>(
656 shell, // delegate
657 shell.GetTaskRunners(), // task runners
658 std::move(embedder_surface), // embedder surface
659 platform_dispatch_table, // platform dispatch table
660 std::move(external_view_embedder) // external view embedder
661 );
662 });
663#else
664 return nullptr;
665#endif
666}
667
670 const FlutterRendererConfig* config,
671 void* user_data,
673 platform_dispatch_table,
674 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
675 external_view_embedder) {
676 if (config->type != kSoftware) {
677 return nullptr;
678 }
679
680 auto software_present_backing_store =
682 const void* allocation, size_t row_bytes, size_t height) -> bool {
683 return ptr(user_data, allocation, row_bytes, height);
684 };
685
687 software_dispatch_table = {
688 software_present_backing_store, // required
689 };
690
691 return fml::MakeCopyable(
692 [software_dispatch_table, platform_dispatch_table,
693 external_view_embedder =
694 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
695 return std::make_unique<flutter::PlatformViewEmbedder>(
696 shell, // delegate
697 shell.GetTaskRunners(), // task runners
698 software_dispatch_table, // software dispatch table
699 platform_dispatch_table, // platform dispatch table
700 std::move(external_view_embedder) // external view embedder
701 );
702 });
703}
704
707 const FlutterRendererConfig* config,
708 void* user_data,
710 platform_dispatch_table,
711 std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
712 external_view_embedder,
713 bool enable_impeller) {
714 if (config == nullptr) {
715 return nullptr;
716 }
717
718 switch (config->type) {
719 case kOpenGL:
721 config, user_data, platform_dispatch_table,
722 std::move(external_view_embedder), enable_impeller);
723 case kSoftware:
725 config, user_data, platform_dispatch_table,
726 std::move(external_view_embedder));
727 case kMetal:
729 config, user_data, platform_dispatch_table,
730 std::move(external_view_embedder), enable_impeller);
731 case kVulkan:
733 config, user_data, platform_dispatch_table,
734 std::move(external_view_embedder));
735 default:
736 return nullptr;
737 }
738 return nullptr;
739}
740
742 GrDirectContext* context,
743 const FlutterBackingStoreConfig& config,
745#ifdef SHELL_ENABLE_GL
746 GrGLTextureInfo texture_info;
747 texture_info.fTarget = texture->target;
748 texture_info.fID = texture->name;
749 texture_info.fFormat = texture->format;
750
751 GrBackendTexture backend_texture =
753 skgpu::Mipmapped::kNo, texture_info);
754
755 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
756
758 context, // context
759 backend_texture, // back-end texture
760 kBottomLeft_GrSurfaceOrigin, // surface origin
761 1, // sample count
762 kN32_SkColorType, // color type
763 SkColorSpace::MakeSRGB(), // color space
764 &surface_properties, // surface properties
766 texture->destruction_callback), // release proc
767 texture->user_data // release context
768 );
769
770 if (!surface) {
771 FML_LOG(ERROR) << "Could not wrap embedder supplied render texture.";
772 return nullptr;
773 }
774
775 return surface;
776#else
777 return nullptr;
778#endif
779}
780
782 GrDirectContext* context,
783 const FlutterBackingStoreConfig& config,
784 const FlutterOpenGLFramebuffer* framebuffer) {
785#ifdef SHELL_ENABLE_GL
786 GrGLFramebufferInfo framebuffer_info = {};
787 framebuffer_info.fFormat = framebuffer->target;
788 framebuffer_info.fFBOID = framebuffer->name;
789
790 auto backend_render_target =
792 config.size.height, // height
793 1, // sample count
794 0, // stencil bits
795 framebuffer_info // framebuffer info
796 );
797
798 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
799
801 context, // context
802 backend_render_target, // backend render target
803 kBottomLeft_GrSurfaceOrigin, // surface origin
804 kN32_SkColorType, // color type
805 SkColorSpace::MakeSRGB(), // color space
806 &surface_properties, // surface properties
808 framebuffer->destruction_callback), // release proc
809 framebuffer->user_data // release context
810 );
811
812 if (!surface) {
813 FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
814 return nullptr;
815 }
816 return surface;
817#else
818 return nullptr;
819#endif
820}
821
823 GrDirectContext* context,
824 const FlutterBackingStoreConfig& config,
825 const FlutterSoftwareBackingStore* software) {
826 const auto image_info =
828
829 struct Captures {
830 VoidCallback destruction_callback;
831 void* user_data;
832 };
833 auto captures = std::make_unique<Captures>();
834 captures->destruction_callback = software->destruction_callback;
835 captures->user_data = software->user_data;
836 auto release_proc = [](void* pixels, void* context) {
837 auto captures = reinterpret_cast<Captures*>(context);
838 if (captures->destruction_callback) {
839 captures->destruction_callback(captures->user_data);
840 }
841 delete captures;
842 };
843
844 auto surface =
845 SkSurfaces::WrapPixels(image_info, // image info
846 const_cast<void*>(software->allocation), // pixels
847 software->row_bytes, // row bytes
848 release_proc, // release proc
849 captures.get() // get context
850 );
851
852 if (!surface) {
854 << "Could not wrap embedder supplied software render buffer.";
855 if (software->destruction_callback) {
856 software->destruction_callback(software->user_data);
857 }
858 return nullptr;
859 }
860 if (surface) {
861 captures.release(); // Skia has assumed ownership of the struct.
862 }
863 return surface;
864}
865
867 GrDirectContext* context,
868 const FlutterBackingStoreConfig& config,
869 const FlutterSoftwareBackingStore2* software) {
870 const auto color_info = getSkColorInfo(software->pixel_format);
871 if (!color_info) {
872 return nullptr;
873 }
874
875 const auto image_info = SkImageInfo::Make(
876 SkISize::Make(config.size.width, config.size.height), *color_info);
877
878 struct Captures {
879 VoidCallback destruction_callback;
880 void* user_data;
881 };
882 auto captures = std::make_unique<Captures>();
883 captures->destruction_callback = software->destruction_callback;
884 captures->user_data = software->user_data;
885 auto release_proc = [](void* pixels, void* context) {
886 auto captures = reinterpret_cast<Captures*>(context);
887 if (captures->destruction_callback) {
888 captures->destruction_callback(captures->user_data);
889 }
890 };
891
892 auto surface =
893 SkSurfaces::WrapPixels(image_info, // image info
894 const_cast<void*>(software->allocation), // pixels
895 software->row_bytes, // row bytes
896 release_proc, // release proc
897 captures.release() // release context
898 );
899
900 if (!surface) {
902 << "Could not wrap embedder supplied software render buffer.";
903 if (software->destruction_callback) {
904 software->destruction_callback(software->user_data);
905 }
906 return nullptr;
907 }
908 return surface;
909}
910
912 GrDirectContext* context,
913 const FlutterBackingStoreConfig& config,
914 const FlutterMetalBackingStore* metal) {
915#ifdef SHELL_ENABLE_METAL
916 GrMtlTextureInfo texture_info;
917 if (!metal->texture.texture) {
918 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
919 return nullptr;
920 }
921 sk_cfp<FlutterMetalTextureHandle> mtl_texture;
922 mtl_texture.retain(metal->texture.texture);
923 texture_info.fTexture = mtl_texture;
924 GrBackendTexture backend_texture =
926 config.size.height, //
927 skgpu::Mipmapped::kNo, //
928 texture_info //
929 );
930
931 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
932
934 context, // context
935 backend_texture, // back-end texture
936 kTopLeft_GrSurfaceOrigin, // surface origin
937 // TODO(dnfield): Update this when embedders support MSAA, see
938 // https://github.com/flutter/flutter/issues/100392
939 1, // sample count
940 kBGRA_8888_SkColorType, // color type
941 nullptr, // color space
942 &surface_properties, // surface properties
944 metal->texture.destruction_callback), // release proc
945 metal->texture.user_data // release context
946 );
947
948 if (!surface) {
949 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
950 return nullptr;
951 }
952
953 return surface;
954#else
955 return nullptr;
956#endif
957}
958
959static std::unique_ptr<flutter::EmbedderRenderTarget>
961 FlutterBackingStore backing_store,
962 const fml::closure& on_release,
963 const std::shared_ptr<impeller::AiksContext>& aiks_context,
964 const FlutterBackingStoreConfig& config,
965 const FlutterOpenGLFramebuffer* framebuffer) {
966#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
967
968 const auto& gl_context =
969 impeller::ContextGLES::Cast(*aiks_context->GetContext());
970 const auto size = impeller::ISize(config.size.width, config.size.height);
971
975 color0_tex.size = size;
976 color0_tex.usage = static_cast<impeller::TextureUsageMask>(
980
983 gl_context.GetReactor(), color0_tex, framebuffer->name);
987
988 impeller::TextureDescriptor depth_stencil_texture_desc;
989 depth_stencil_texture_desc.type = impeller::TextureType::kTexture2D;
990 depth_stencil_texture_desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
991 depth_stencil_texture_desc.size = size;
992 depth_stencil_texture_desc.usage = static_cast<impeller::TextureUsageMask>(
994 depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount1;
995
996 auto depth_stencil_tex = std::make_shared<impeller::TextureGLES>(
997 gl_context.GetReactor(), depth_stencil_texture_desc,
999
1001 depth0.clear_depth = 0;
1002 depth0.texture = depth_stencil_tex;
1005
1007 stencil0.clear_stencil = 0;
1008 stencil0.texture = depth_stencil_tex;
1011
1012 impeller::RenderTarget render_target_desc;
1013
1014 render_target_desc.SetColorAttachment(color0, 0u);
1015 render_target_desc.SetDepthAttachment(depth0);
1016 render_target_desc.SetStencilAttachment(stencil0);
1017
1018 fml::closure framebuffer_destruct =
1019 [callback = framebuffer->destruction_callback,
1020 user_data = framebuffer->user_data]() { callback(user_data); };
1021
1022 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1023 backing_store, aiks_context,
1024 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1025 on_release, framebuffer_destruct);
1026#else
1027 return nullptr;
1028#endif
1029}
1030
1031static std::unique_ptr<flutter::EmbedderRenderTarget>
1033 FlutterBackingStore backing_store,
1034 const fml::closure& on_release,
1035 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1036 const FlutterBackingStoreConfig& config,
1037 const FlutterMetalBackingStore* metal) {
1038#if defined(SHELL_ENABLE_METAL) && defined(IMPELLER_SUPPORTS_RENDERING)
1039 if (!metal->texture.texture) {
1040 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
1041 return nullptr;
1042 }
1043
1044 const auto size = impeller::ISize(config.size.width, config.size.height);
1045
1046 impeller::TextureDescriptor resolve_tex_desc;
1047 resolve_tex_desc.size = size;
1050 resolve_tex_desc.usage = impeller::TextureUsage::kRenderTarget |
1052
1053 auto resolve_tex = impeller::WrapTextureMTL(
1054 resolve_tex_desc, metal->texture.texture,
1056 user_data = metal->texture.user_data]() { callback(user_data); });
1057 if (!resolve_tex) {
1058 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
1059 return nullptr;
1060 }
1061 resolve_tex->SetLabel("ImpellerBackingStoreResolve");
1062
1063 impeller::TextureDescriptor msaa_tex_desc;
1067 msaa_tex_desc.format = resolve_tex->GetTextureDescriptor().format;
1068 msaa_tex_desc.size = size;
1070
1071 auto msaa_tex =
1072 aiks_context->GetContext()->GetResourceAllocator()->CreateTexture(
1073 msaa_tex_desc);
1074 if (!msaa_tex) {
1075 FML_LOG(ERROR) << "Could not allocate MSAA color texture.";
1076 return nullptr;
1077 }
1078 msaa_tex->SetLabel("ImpellerBackingStoreColorMSAA");
1079
1081 color0.texture = msaa_tex;
1085 color0.resolve_texture = resolve_tex;
1086
1087 impeller::RenderTarget render_target_desc;
1088 render_target_desc.SetColorAttachment(color0, 0u);
1089
1090 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1091 backing_store, aiks_context,
1092 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1093 on_release, fml::closure());
1094#else
1095 return nullptr;
1096#endif
1097}
1098
1100 GrDirectContext* context,
1101 const FlutterBackingStoreConfig& config,
1103#ifdef SHELL_ENABLE_VULKAN
1104 if (!vulkan->image) {
1105 FML_LOG(ERROR) << "Embedder supplied null Vulkan image.";
1106 return nullptr;
1107 }
1108 GrVkImageInfo image_info = {
1109 .fImage = reinterpret_cast<VkImage>(vulkan->image->image),
1110 .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
1111 .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1112 .fFormat = static_cast<VkFormat>(vulkan->image->format),
1113 .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1117 .fSampleCount = 1,
1118 .fLevelCount = 1,
1119 };
1120 auto backend_texture = GrBackendTextures::MakeVk(
1121 config.size.width, config.size.height, image_info);
1122
1123 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
1124
1126 context, // context
1127 backend_texture, // back-end texture
1128 kTopLeft_GrSurfaceOrigin, // surface origin
1129 1, // sample count
1131 static_cast<VkFormat>(vulkan->image->format)), // color type
1132 SkColorSpace::MakeSRGB(), // color space
1133 &surface_properties, // surface properties
1134 static_cast<SkSurfaces::TextureReleaseProc>(
1135 vulkan->destruction_callback), // release proc
1136 vulkan->user_data // release context
1137 );
1138
1139 if (!surface) {
1140 FML_LOG(ERROR) << "Could not wrap embedder supplied Vulkan render texture.";
1141 return nullptr;
1142 }
1143
1144 return surface;
1145#else
1146 return nullptr;
1147#endif
1148}
1149
1150static std::unique_ptr<flutter::EmbedderRenderTarget>
1152 sk_sp<SkSurface> skia_surface,
1153 fml::closure on_release) {
1154 if (!skia_surface) {
1155 return nullptr;
1156 }
1157 return std::make_unique<flutter::EmbedderRenderTargetSkia>(
1158 backing_store, std::move(skia_surface), std::move(on_release));
1159}
1160
1161static std::unique_ptr<flutter::EmbedderRenderTarget>
1163 const FlutterCompositor* compositor,
1164 const FlutterBackingStoreConfig& config,
1165 GrDirectContext* context,
1166 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1167 bool enable_impeller) {
1168 FlutterBackingStore backing_store = {};
1169 backing_store.struct_size = sizeof(backing_store);
1170
1171 // Safe access checks on the compositor struct have been performed in
1172 // InferExternalViewEmbedderFromArgs and are not necessary here.
1173 auto c_create_callback = compositor->create_backing_store_callback;
1174 auto c_collect_callback = compositor->collect_backing_store_callback;
1175
1176 {
1177 TRACE_EVENT0("flutter", "FlutterCompositorCreateBackingStore");
1178 if (!c_create_callback(&config, &backing_store, compositor->user_data)) {
1179 FML_LOG(ERROR) << "Could not create the embedder backing store.";
1180 return nullptr;
1181 }
1182 }
1183
1184 if (backing_store.struct_size != sizeof(backing_store)) {
1185 FML_LOG(ERROR) << "Embedder modified the backing store struct size.";
1186 return nullptr;
1187 }
1188
1189 // In case we return early without creating an embedder render target, the
1190 // embedder has still given us ownership of its baton which we must return
1191 // back to it. If this method is successful, the closure is released when the
1192 // render target is eventually released.
1193 fml::ScopedCleanupClosure collect_callback(
1194 [c_collect_callback, backing_store, user_data = compositor->user_data]() {
1195 TRACE_EVENT0("flutter", "FlutterCompositorCollectBackingStore");
1196 c_collect_callback(&backing_store, user_data);
1197 });
1198
1199 // No safe access checks on the renderer are necessary since we allocated
1200 // the struct.
1201
1202 std::unique_ptr<flutter::EmbedderRenderTarget> render_target;
1203
1204 switch (backing_store.type) {
1206 switch (backing_store.open_gl.type) {
1208 auto skia_surface = MakeSkSurfaceFromBackingStore(
1209 context, config, &backing_store.open_gl.texture);
1210 render_target = MakeRenderTargetFromSkSurface(
1211 backing_store, std::move(skia_surface),
1212 collect_callback.Release());
1213 break;
1214 }
1216 if (enable_impeller) {
1218 backing_store, collect_callback.Release(), aiks_context, config,
1219 &backing_store.open_gl.framebuffer);
1220 break;
1221 } else {
1222 auto skia_surface = MakeSkSurfaceFromBackingStore(
1223 context, config, &backing_store.open_gl.framebuffer);
1224 render_target = MakeRenderTargetFromSkSurface(
1225 backing_store, std::move(skia_surface),
1226 collect_callback.Release());
1227 break;
1228 }
1229 }
1230 }
1231 break;
1232 }
1234 auto skia_surface = MakeSkSurfaceFromBackingStore(
1235 context, config, &backing_store.software);
1236 render_target = MakeRenderTargetFromSkSurface(
1237 backing_store, std::move(skia_surface), collect_callback.Release());
1238 break;
1239 }
1241 auto skia_surface = MakeSkSurfaceFromBackingStore(
1242 context, config, &backing_store.software2);
1243 render_target = MakeRenderTargetFromSkSurface(
1244 backing_store, std::move(skia_surface), collect_callback.Release());
1245 break;
1246 }
1248 if (enable_impeller) {
1250 backing_store, collect_callback.Release(), aiks_context, config,
1251 &backing_store.metal);
1252 } else {
1253 auto skia_surface = MakeSkSurfaceFromBackingStore(context, config,
1254 &backing_store.metal);
1255 render_target = MakeRenderTargetFromSkSurface(
1256 backing_store, std::move(skia_surface), collect_callback.Release());
1257 }
1258 break;
1259 }
1261 auto skia_surface =
1262 MakeSkSurfaceFromBackingStore(context, config, &backing_store.vulkan);
1263 render_target = MakeRenderTargetFromSkSurface(
1264 backing_store, std::move(skia_surface), collect_callback.Release());
1265 break;
1266 }
1267 };
1268
1269 if (!render_target) {
1270 FML_LOG(ERROR) << "Could not create a surface from an embedder provided "
1271 "render target.";
1272 }
1273 return render_target;
1274}
1275
1276static std::pair<std::unique_ptr<flutter::EmbedderExternalViewEmbedder>,
1277 bool /* halt engine launch if true */>
1279 bool enable_impeller) {
1280 if (compositor == nullptr) {
1281 return {nullptr, false};
1282 }
1283
1284 auto c_create_callback =
1285 SAFE_ACCESS(compositor, create_backing_store_callback, nullptr);
1286 auto c_collect_callback =
1287 SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr);
1288 auto c_present_callback =
1289 SAFE_ACCESS(compositor, present_layers_callback, nullptr);
1290 auto c_present_view_callback =
1291 SAFE_ACCESS(compositor, present_view_callback, nullptr);
1292 bool avoid_backing_store_cache =
1293 SAFE_ACCESS(compositor, avoid_backing_store_cache, false);
1294
1295 // Make sure the required callbacks are present
1296 if (!c_create_callback || !c_collect_callback) {
1297 FML_LOG(ERROR) << "Required compositor callbacks absent.";
1298 return {nullptr, true};
1299 }
1300 // Either the present view or the present layers callback must be provided.
1301 if ((!c_present_view_callback && !c_present_callback) ||
1302 (c_present_view_callback && c_present_callback)) {
1303 FML_LOG(ERROR) << "Either present_layers_callback or present_view_callback "
1304 "must be provided but not both.";
1305 return {nullptr, true};
1306 }
1307
1308 FlutterCompositor captured_compositor = *compositor;
1309
1311 create_render_target_callback =
1312 [captured_compositor, enable_impeller](
1313 GrDirectContext* context,
1314 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1315 const auto& config) {
1316 return CreateEmbedderRenderTarget(&captured_compositor, config,
1317 context, aiks_context,
1318 enable_impeller);
1319 };
1320
1322 if (c_present_callback) {
1323 present_callback = [c_present_callback, user_data = compositor->user_data](
1324 FlutterViewId view_id, const auto& layers) {
1325 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1326 return c_present_callback(const_cast<const FlutterLayer**>(layers.data()),
1327 layers.size(), user_data);
1328 };
1329 } else {
1330 FML_DCHECK(c_present_view_callback != nullptr);
1331 present_callback = [c_present_view_callback,
1332 user_data = compositor->user_data](
1333 FlutterViewId view_id, const auto& layers) {
1334 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1335
1338 .view_id = view_id,
1339 .layers = const_cast<const FlutterLayer**>(layers.data()),
1340 .layers_count = layers.size(),
1341 .user_data = user_data,
1342 };
1343
1344 return c_present_view_callback(&info);
1345 };
1346 }
1347
1348 return {std::make_unique<flutter::EmbedderExternalViewEmbedder>(
1349 avoid_backing_store_cache, create_render_target_callback,
1350 present_callback),
1351 false};
1352}
1353
1354// Translates embedder metrics to engine metrics, or returns a string on error.
1355static std::variant<flutter::ViewportMetrics, std::string>
1357 const FlutterWindowMetricsEvent* flutter_metrics) {
1358 if (flutter_metrics == nullptr) {
1359 return "Invalid metrics handle.";
1360 }
1361
1363
1364 metrics.physical_width = SAFE_ACCESS(flutter_metrics, width, 0.0);
1365 metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
1366 metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
1367 metrics.physical_view_inset_top =
1368 SAFE_ACCESS(flutter_metrics, physical_view_inset_top, 0.0);
1370 SAFE_ACCESS(flutter_metrics, physical_view_inset_right, 0.0);
1372 SAFE_ACCESS(flutter_metrics, physical_view_inset_bottom, 0.0);
1373 metrics.physical_view_inset_left =
1374 SAFE_ACCESS(flutter_metrics, physical_view_inset_left, 0.0);
1375 metrics.display_id = SAFE_ACCESS(flutter_metrics, display_id, 0);
1376
1377 if (metrics.device_pixel_ratio <= 0.0) {
1378 return "Device pixel ratio was invalid. It must be greater than zero.";
1379 }
1380
1381 if (metrics.physical_view_inset_top < 0 ||
1382 metrics.physical_view_inset_right < 0 ||
1383 metrics.physical_view_inset_bottom < 0 ||
1384 metrics.physical_view_inset_left < 0) {
1385 return "Physical view insets are invalid. They must be non-negative.";
1386 }
1387
1388 if (metrics.physical_view_inset_top > metrics.physical_height ||
1389 metrics.physical_view_inset_right > metrics.physical_width ||
1390 metrics.physical_view_inset_bottom > metrics.physical_height ||
1391 metrics.physical_view_inset_left > metrics.physical_width) {
1392 return "Physical view insets are invalid. They cannot be greater than "
1393 "physical height or width.";
1394 }
1395
1396 return metrics;
1397}
1398
1400 std::unique_ptr<flutter::PlatformMessage> message;
1401};
1402
1403struct LoadedElfDeleter {
1404 void operator()(Dart_LoadedElf* elf) {
1405 if (elf) {
1406 ::Dart_UnloadELF(elf);
1407 }
1408 }
1409};
1410
1411using UniqueLoadedElf = std::unique_ptr<Dart_LoadedElf, LoadedElfDeleter>;
1412
1413struct _FlutterEngineAOTData {
1414 UniqueLoadedElf loaded_elf = nullptr;
1415 const uint8_t* vm_snapshot_data = nullptr;
1416 const uint8_t* vm_snapshot_instrs = nullptr;
1417 const uint8_t* vm_isolate_data = nullptr;
1418 const uint8_t* vm_isolate_instrs = nullptr;
1419};
1420
1423 FlutterEngineAOTData* data_out) {
1426 "AOT data can only be created in AOT mode.");
1427 } else if (!source) {
1428 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null source specified.");
1429 } else if (!data_out) {
1430 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null data_out specified.");
1431 }
1432
1433 switch (source->type) {
1435 if (!source->elf_path || !fml::IsFile(source->elf_path)) {
1437 "Invalid ELF path specified.");
1438 }
1439
1440 auto aot_data = std::make_unique<_FlutterEngineAOTData>();
1441 const char* error = nullptr;
1442
1443#if OS_FUCHSIA
1444 // TODO(gw280): https://github.com/flutter/flutter/issues/50285
1445 // Dart doesn't implement Dart_LoadELF on Fuchsia
1446 Dart_LoadedElf* loaded_elf = nullptr;
1447#else
1448 Dart_LoadedElf* loaded_elf = Dart_LoadELF(
1449 source->elf_path, // file path
1450 0, // file offset
1451 &error, // error (out)
1452 &aot_data->vm_snapshot_data, // vm snapshot data (out)
1453 &aot_data->vm_snapshot_instrs, // vm snapshot instr (out)
1454 &aot_data->vm_isolate_data, // vm isolate data (out)
1455 &aot_data->vm_isolate_instrs // vm isolate instr (out)
1456 );
1457#endif
1458
1459 if (loaded_elf == nullptr) {
1461 }
1462
1463 aot_data->loaded_elf.reset(loaded_elf);
1464
1465 *data_out = aot_data.release();
1466 return kSuccess;
1467 }
1468 }
1469
1470 return LOG_EMBEDDER_ERROR(
1472 "Invalid FlutterEngineAOTDataSourceType type specified.");
1473}
1474
1476 if (!data) {
1477 // Deleting a null object should be a no-op.
1478 return kSuccess;
1479 }
1480
1481 // Created in a unique pointer in `FlutterEngineCreateAOTData`.
1482 delete data;
1483 return kSuccess;
1484}
1485
1486// Constructs appropriate mapping callbacks if JIT snapshot locations have been
1487// explictly specified.
1489 flutter::Settings& settings) {
1490 auto make_mapping_callback = [](const char* path, bool executable) {
1491 return [path, executable]() {
1492 if (executable) {
1494 } else {
1496 }
1497 };
1498 };
1499
1500 // Users are allowed to specify only certain snapshots if they so desire.
1501 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1502 settings.vm_snapshot_data = make_mapping_callback(
1503 reinterpret_cast<const char*>(args->vm_snapshot_data), false);
1504 }
1505
1506 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1507 settings.vm_snapshot_instr = make_mapping_callback(
1508 reinterpret_cast<const char*>(args->vm_snapshot_instructions), true);
1509 }
1510
1511 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1512 settings.isolate_snapshot_data = make_mapping_callback(
1513 reinterpret_cast<const char*>(args->isolate_snapshot_data), false);
1514 }
1515
1516 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1517 settings.isolate_snapshot_instr = make_mapping_callback(
1518 reinterpret_cast<const char*>(args->isolate_snapshot_instructions),
1519 true);
1520 }
1521
1522#if !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
1523 settings.dart_library_sources_kernel = []() {
1524 return std::make_unique<fml::NonOwnedMapping>(kPlatformStrongDill,
1526 };
1527#endif // !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE ==
1528 // FLUTTER_RUNTIME_MODE_DEBUG)
1529}
1530
1532 const FlutterProjectArgs* args,
1533 flutter::Settings& settings) { // NOLINT(google-runtime-references)
1534 // There are no ownership concerns here as all mappings are owned by the
1535 // embedder and not the engine.
1536 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
1537 return [mapping, size]() {
1538 return std::make_unique<fml::NonOwnedMapping>(mapping, size);
1539 };
1540 };
1541
1542 if (SAFE_ACCESS(args, aot_data, nullptr) != nullptr) {
1543 settings.vm_snapshot_data =
1544 make_mapping_callback(args->aot_data->vm_snapshot_data, 0);
1545
1546 settings.vm_snapshot_instr =
1547 make_mapping_callback(args->aot_data->vm_snapshot_instrs, 0);
1548
1549 settings.isolate_snapshot_data =
1550 make_mapping_callback(args->aot_data->vm_isolate_data, 0);
1551
1552 settings.isolate_snapshot_instr =
1553 make_mapping_callback(args->aot_data->vm_isolate_instrs, 0);
1554 }
1555
1556 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1557 settings.vm_snapshot_data = make_mapping_callback(
1558 args->vm_snapshot_data, SAFE_ACCESS(args, vm_snapshot_data_size, 0));
1559 }
1560
1561 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1562 settings.vm_snapshot_instr = make_mapping_callback(
1563 args->vm_snapshot_instructions,
1564 SAFE_ACCESS(args, vm_snapshot_instructions_size, 0));
1565 }
1566
1567 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1568 settings.isolate_snapshot_data =
1569 make_mapping_callback(args->isolate_snapshot_data,
1570 SAFE_ACCESS(args, isolate_snapshot_data_size, 0));
1571 }
1572
1573 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1574 settings.isolate_snapshot_instr = make_mapping_callback(
1575 args->isolate_snapshot_instructions,
1576 SAFE_ACCESS(args, isolate_snapshot_instructions_size, 0));
1577 }
1578}
1579
1580// Create a callback to notify the embedder of semantic updates
1581// using the legacy embedder callbacks 'update_semantics_node_callback' and
1582// 'update_semantics_custom_action_callback'.
1585 FlutterUpdateSemanticsNodeCallback update_semantics_node_callback,
1587 update_semantics_custom_action_callback,
1588 void* user_data) {
1589 return [update_semantics_node_callback,
1590 update_semantics_custom_action_callback,
1594 FlutterSemanticsUpdate* update_ptr = update.get();
1595
1596 // First, queue all node and custom action updates.
1597 if (update_semantics_node_callback != nullptr) {
1598 for (size_t i = 0; i < update_ptr->nodes_count; i++) {
1599 update_semantics_node_callback(&update_ptr->nodes[i], user_data);
1600 }
1601 }
1602
1603 if (update_semantics_custom_action_callback != nullptr) {
1604 for (size_t i = 0; i < update_ptr->custom_actions_count; i++) {
1605 update_semantics_custom_action_callback(&update_ptr->custom_actions[i],
1606 user_data);
1607 }
1608 }
1609
1610 // Second, mark node and action batches completed now that all
1611 // updates are queued.
1612 if (update_semantics_node_callback != nullptr) {
1613 const FlutterSemanticsNode batch_end_sentinel = {
1614 sizeof(FlutterSemanticsNode),
1616 };
1617 update_semantics_node_callback(&batch_end_sentinel, user_data);
1618 }
1619
1620 if (update_semantics_custom_action_callback != nullptr) {
1621 const FlutterSemanticsCustomAction batch_end_sentinel = {
1624 };
1625 update_semantics_custom_action_callback(&batch_end_sentinel, user_data);
1626 }
1627 };
1628}
1629
1630// Create a callback to notify the embedder of semantic updates
1631// using the deprecated embedder callback 'update_semantics_callback'.
1634 FlutterUpdateSemanticsCallback update_semantics_callback,
1635 void* user_data) {
1636 return [update_semantics_callback, user_data](
1637 const flutter::SemanticsNodeUpdates& nodes,
1640
1641 update_semantics_callback(update.get(), user_data);
1642 };
1643}
1644
1645// Create a callback to notify the embedder of semantic updates
1646// using the new embedder callback 'update_semantics_callback2'.
1649 FlutterUpdateSemanticsCallback2 update_semantics_callback,
1650 void* user_data) {
1651 return [update_semantics_callback, user_data](
1652 const flutter::SemanticsNodeUpdates& nodes,
1655
1656 update_semantics_callback(update.get(), user_data);
1657 };
1658}
1659
1660// Creates a callback that receives semantic updates from the engine
1661// and notifies the embedder's callback(s). Returns null if the embedder
1662// did not register any callbacks.
1665 void* user_data) {
1666 // There are three variants for the embedder API's semantic update callbacks.
1667 // Create a callback that maps to the embedder's desired semantic update API.
1668 //
1669 // Handle the case where the embedder registered the callback
1670 // 'updated_semantics_callback2'
1671 if (SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr) {
1673 args->update_semantics_callback2, user_data);
1674 }
1675
1676 // Handle the case where the embedder registered the deprecated callback
1677 // 'update_semantics_callback'.
1678 if (SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr) {
1680 args->update_semantics_callback, user_data);
1681 }
1682
1683 // Handle the case where the embedder registered the deprecated callbacks
1684 // 'update_semantics_node_callback' and
1685 // 'update_semantics_custom_action_callback'.
1686 FlutterUpdateSemanticsNodeCallback update_semantics_node_callback = nullptr;
1687 if (SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr) {
1688 update_semantics_node_callback = args->update_semantics_node_callback;
1689 }
1690
1692 update_semantics_custom_action_callback = nullptr;
1693 if (SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
1694 nullptr) {
1695 update_semantics_custom_action_callback =
1696 args->update_semantics_custom_action_callback;
1697 }
1698
1699 if (update_semantics_node_callback != nullptr ||
1700 update_semantics_custom_action_callback != nullptr) {
1702 update_semantics_node_callback, update_semantics_custom_action_callback,
1703 user_data);
1704 }
1705
1706 // Handle the case where the embedder registered no callbacks.
1707 return nullptr;
1708}
1709
1711 const FlutterRendererConfig* config,
1712 const FlutterProjectArgs* args,
1713 void* user_data,
1715 engine_out) {
1716 auto result =
1717 FlutterEngineInitialize(version, config, args, user_data, engine_out);
1718
1719 if (result != kSuccess) {
1720 return result;
1721 }
1722
1723 return FlutterEngineRunInitialized(*engine_out);
1724}
1725
1727 const FlutterRendererConfig* config,
1728 const FlutterProjectArgs* args,
1729 void* user_data,
1731 engine_out) {
1732 // Step 0: Figure out arguments for shell creation.
1733 if (version != FLUTTER_ENGINE_VERSION) {
1734 return LOG_EMBEDDER_ERROR(
1736 "Flutter embedder version mismatch. There has been a breaking change. "
1737 "Please consult the changelog and update the embedder.");
1738 }
1739
1740 if (engine_out == nullptr) {
1742 "The engine out parameter was missing.");
1743 }
1744
1745 if (args == nullptr) {
1747 "The Flutter project arguments were missing.");
1748 }
1749
1750 if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr) {
1751 return LOG_EMBEDDER_ERROR(
1753 "The assets path in the Flutter project arguments was missing.");
1754 }
1755
1756 if (SAFE_ACCESS(args, main_path__unused__, nullptr) != nullptr) {
1757 FML_LOG(WARNING)
1758 << "FlutterProjectArgs.main_path is deprecated and should be set null.";
1759 }
1760
1761 if (SAFE_ACCESS(args, packages_path__unused__, nullptr) != nullptr) {
1762 FML_LOG(WARNING) << "FlutterProjectArgs.packages_path is deprecated and "
1763 "should be set null.";
1764 }
1765
1766 if (!IsRendererValid(config)) {
1768 "The renderer configuration was invalid.");
1769 }
1770
1771 std::string icu_data_path;
1772 if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) {
1773 icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr);
1774 }
1775
1776 if (SAFE_ACCESS(args, persistent_cache_path, nullptr) != nullptr) {
1777 std::string persistent_cache_path =
1778 SAFE_ACCESS(args, persistent_cache_path, nullptr);
1780 }
1781
1782 if (SAFE_ACCESS(args, is_persistent_cache_read_only, false)) {
1784 }
1785
1786 fml::CommandLine command_line;
1787 if (SAFE_ACCESS(args, command_line_argc, 0) != 0 &&
1788 SAFE_ACCESS(args, command_line_argv, nullptr) != nullptr) {
1789 command_line = fml::CommandLineFromArgcArgv(
1790 SAFE_ACCESS(args, command_line_argc, 0),
1791 SAFE_ACCESS(args, command_line_argv, nullptr));
1792 }
1793
1795
1796 if (SAFE_ACCESS(args, aot_data, nullptr)) {
1797 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) ||
1798 SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) ||
1799 SAFE_ACCESS(args, isolate_snapshot_data, nullptr) ||
1800 SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr)) {
1801 return LOG_EMBEDDER_ERROR(
1803 "Multiple AOT sources specified. Embedders should provide either "
1804 "*_snapshot_* buffers or aot_data, not both.");
1805 }
1806 }
1807
1810 } else {
1812 }
1813
1814 settings.icu_data_path = icu_data_path;
1815 settings.assets_path = args->assets_path;
1816 settings.leak_vm = !SAFE_ACCESS(args, shutdown_dart_vm_when_done, false);
1817 settings.old_gen_heap_size = SAFE_ACCESS(args, dart_old_gen_heap_size, -1);
1818
1820 // Verify the assets path contains Dart 2 kernel assets.
1821 const std::string kApplicationKernelSnapshotFileName = "kernel_blob.bin";
1822 std::string application_kernel_path = fml::paths::JoinPaths(
1824 if (!fml::IsFile(application_kernel_path)) {
1825 return LOG_EMBEDDER_ERROR(
1827 "Not running in AOT mode but could not resolve the kernel binary.");
1828 }
1829 settings.application_kernel_asset = kApplicationKernelSnapshotFileName;
1830 }
1831
1832 settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
1834 };
1835 settings.task_observer_remove = [](intptr_t key) {
1837 };
1838 if (SAFE_ACCESS(args, root_isolate_create_callback, nullptr) != nullptr) {
1840 SAFE_ACCESS(args, root_isolate_create_callback, nullptr);
1841 settings.root_isolate_create_callback =
1842 [callback, user_data](const auto& isolate) { callback(user_data); };
1843 }
1844 if (SAFE_ACCESS(args, log_message_callback, nullptr) != nullptr) {
1846 SAFE_ACCESS(args, log_message_callback, nullptr);
1847 settings.log_message_callback = [callback, user_data](
1848 const std::string& tag,
1849 const std::string& message) {
1850 callback(tag.c_str(), message.c_str(), user_data);
1851 };
1852 }
1853 if (SAFE_ACCESS(args, log_tag, nullptr) != nullptr) {
1854 settings.log_tag = SAFE_ACCESS(args, log_tag, nullptr);
1855 }
1856
1857 bool has_update_semantics_2_callback =
1858 SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr;
1859 bool has_update_semantics_callback =
1860 SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr;
1861 bool has_legacy_update_semantics_callback =
1862 SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr ||
1863 SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
1864 nullptr;
1865
1866 int semantic_callback_count = (has_update_semantics_2_callback ? 1 : 0) +
1867 (has_update_semantics_callback ? 1 : 0) +
1868 (has_legacy_update_semantics_callback ? 1 : 0);
1869
1870 if (semantic_callback_count > 1) {
1871 return LOG_EMBEDDER_ERROR(
1873 "Multiple semantics update callbacks provided. "
1874 "Embedders should provide either `update_semantics_callback2`, "
1875 "`update_semantics_callback`, or both "
1876 "`update_semantics_node_callback` and "
1877 "`update_semantics_custom_action_callback`.");
1878 }
1879
1881 update_semantics_callback =
1883
1885 platform_message_response_callback = nullptr;
1886 if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) {
1887 platform_message_response_callback =
1888 [ptr = args->platform_message_callback,
1889 user_data](std::unique_ptr<flutter::PlatformMessage> message) {
1890 auto handle = new FlutterPlatformMessageResponseHandle();
1891 const FlutterPlatformMessage incoming_message = {
1892 sizeof(FlutterPlatformMessage), // struct_size
1893 message->channel().c_str(), // channel
1894 message->data().GetMapping(), // message
1895 message->data().GetSize(), // message_size
1896 handle, // response_handle
1897 };
1898 handle->message = std::move(message);
1899 return ptr(&incoming_message, user_data);
1900 };
1901 }
1902
1903 flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr;
1904 if (SAFE_ACCESS(args, vsync_callback, nullptr) != nullptr) {
1905 vsync_callback = [ptr = args->vsync_callback, user_data](intptr_t baton) {
1906 return ptr(user_data, baton);
1907 };
1908 }
1909
1911 compute_platform_resolved_locale_callback = nullptr;
1912 if (SAFE_ACCESS(args, compute_platform_resolved_locale_callback, nullptr) !=
1913 nullptr) {
1914 compute_platform_resolved_locale_callback =
1915 [ptr = args->compute_platform_resolved_locale_callback](
1916 const std::vector<std::string>& supported_locales_data) {
1917 const size_t number_of_strings_per_locale = 3;
1918 size_t locale_count =
1919 supported_locales_data.size() / number_of_strings_per_locale;
1920 std::vector<FlutterLocale> supported_locales;
1921 std::vector<const FlutterLocale*> supported_locales_ptr;
1922 for (size_t i = 0; i < locale_count; ++i) {
1923 supported_locales.push_back(
1924 {.struct_size = sizeof(FlutterLocale),
1925 .language_code =
1926 supported_locales_data[i * number_of_strings_per_locale +
1927 0]
1928 .c_str(),
1929 .country_code =
1930 supported_locales_data[i * number_of_strings_per_locale +
1931 1]
1932 .c_str(),
1933 .script_code =
1934 supported_locales_data[i * number_of_strings_per_locale +
1935 2]
1936 .c_str(),
1937 .variant_code = nullptr});
1938 supported_locales_ptr.push_back(&supported_locales[i]);
1939 }
1940
1941 const FlutterLocale* result =
1942 ptr(supported_locales_ptr.data(), locale_count);
1943
1944 std::unique_ptr<std::vector<std::string>> out =
1945 std::make_unique<std::vector<std::string>>();
1946 if (result) {
1947 std::string language_code(SAFE_ACCESS(result, language_code, ""));
1948 if (language_code != "") {
1949 out->push_back(language_code);
1950 out->emplace_back(SAFE_ACCESS(result, country_code, ""));
1951 out->emplace_back(SAFE_ACCESS(result, script_code, ""));
1952 }
1953 }
1954 return out;
1955 };
1956 }
1957
1959 on_pre_engine_restart_callback = nullptr;
1960 if (SAFE_ACCESS(args, on_pre_engine_restart_callback, nullptr) != nullptr) {
1961 on_pre_engine_restart_callback = [ptr =
1962 args->on_pre_engine_restart_callback,
1963 user_data]() { return ptr(user_data); };
1964 }
1965
1967 nullptr;
1968 if (SAFE_ACCESS(args, channel_update_callback, nullptr) != nullptr) {
1969 channel_update_callback = [ptr = args->channel_update_callback, user_data](
1970 const std::string& name, bool listening) {
1972 listening};
1973 ptr(&update, user_data);
1974 };
1975 }
1976
1977 auto external_view_embedder_result = InferExternalViewEmbedderFromArgs(
1978 SAFE_ACCESS(args, compositor, nullptr), settings.enable_impeller);
1979 if (external_view_embedder_result.second) {
1981 "Compositor arguments were invalid.");
1982 }
1983
1985 {
1986 update_semantics_callback, //
1987 platform_message_response_callback, //
1988 vsync_callback, //
1989 compute_platform_resolved_locale_callback, //
1990 on_pre_engine_restart_callback, //
1991 channel_update_callback, //
1992 };
1993
1994 auto on_create_platform_view = InferPlatformViewCreationCallback(
1995 config, user_data, platform_dispatch_table,
1996 std::move(external_view_embedder_result.first), settings.enable_impeller);
1997
1998 if (!on_create_platform_view) {
1999 return LOG_EMBEDDER_ERROR(
2001 "Could not infer platform view creation callback.");
2002 }
2003
2005 [](flutter::Shell& shell) {
2006 return std::make_unique<flutter::Rasterizer>(shell);
2007 };
2008
2009 using ExternalTextureResolver = flutter::EmbedderExternalTextureResolver;
2010 std::unique_ptr<ExternalTextureResolver> external_texture_resolver;
2011 external_texture_resolver = std::make_unique<ExternalTextureResolver>();
2012
2013#ifdef SHELL_ENABLE_GL
2015 external_texture_callback;
2016 if (config->type == kOpenGL) {
2017 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
2018 if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
2019 nullptr) != nullptr) {
2020 external_texture_callback =
2021 [ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
2022 int64_t texture_identifier, size_t width,
2023 size_t height) -> std::unique_ptr<FlutterOpenGLTexture> {
2024 std::unique_ptr<FlutterOpenGLTexture> texture =
2025 std::make_unique<FlutterOpenGLTexture>();
2026 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2027 return nullptr;
2028 }
2029 return texture;
2030 };
2031 external_texture_resolver =
2032 std::make_unique<ExternalTextureResolver>(external_texture_callback);
2033 }
2034 }
2035#endif
2036#ifdef SHELL_ENABLE_METAL
2038 external_texture_metal_callback;
2039 if (config->type == kMetal) {
2040 const FlutterMetalRendererConfig* metal_config = &config->metal;
2041 if (SAFE_ACCESS(metal_config, external_texture_frame_callback, nullptr)) {
2042 external_texture_metal_callback =
2043 [ptr = metal_config->external_texture_frame_callback, user_data](
2044 int64_t texture_identifier, size_t width,
2045 size_t height) -> std::unique_ptr<FlutterMetalExternalTexture> {
2046 std::unique_ptr<FlutterMetalExternalTexture> texture =
2047 std::make_unique<FlutterMetalExternalTexture>();
2048 texture->struct_size = sizeof(FlutterMetalExternalTexture);
2049 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2050 return nullptr;
2051 }
2052 return texture;
2053 };
2054 external_texture_resolver = std::make_unique<ExternalTextureResolver>(
2055 external_texture_metal_callback);
2056 }
2057 }
2058#endif
2059 auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
2060 auto thread_config_callback = [&custom_task_runners](
2061 const fml::Thread::ThreadConfig& config) {
2063 if (!custom_task_runners || !custom_task_runners->thread_priority_setter) {
2064 return;
2065 }
2067 switch (config.priority) {
2070 break;
2073 break;
2076 break;
2079 break;
2080 }
2081 custom_task_runners->thread_priority_setter(priority);
2082 };
2083 auto thread_host =
2085 custom_task_runners, thread_config_callback);
2086
2087 if (!thread_host || !thread_host->IsValid()) {
2089 "Could not set up or infer thread configuration "
2090 "to run the Flutter engine on.");
2091 }
2092
2093 auto task_runners = thread_host->GetTaskRunners();
2094
2095 if (!task_runners.IsValid()) {
2097 "Task runner configuration was invalid.");
2098 }
2099
2100 auto run_configuration =
2102
2103 if (SAFE_ACCESS(args, custom_dart_entrypoint, nullptr) != nullptr) {
2104 auto dart_entrypoint = std::string{args->custom_dart_entrypoint};
2105 if (!dart_entrypoint.empty()) {
2106 run_configuration.SetEntrypoint(std::move(dart_entrypoint));
2107 }
2108 }
2109
2110 if (SAFE_ACCESS(args, dart_entrypoint_argc, 0) > 0) {
2111 if (SAFE_ACCESS(args, dart_entrypoint_argv, nullptr) == nullptr) {
2113 "Could not determine Dart entrypoint arguments "
2114 "as dart_entrypoint_argc "
2115 "was set, but dart_entrypoint_argv was null.");
2116 }
2117 std::vector<std::string> arguments(args->dart_entrypoint_argc);
2118 for (int i = 0; i < args->dart_entrypoint_argc; ++i) {
2119 arguments[i] = std::string{args->dart_entrypoint_argv[i]};
2120 }
2121 run_configuration.SetEntrypointArgs(std::move(arguments));
2122 }
2123
2124 if (!run_configuration.IsValid()) {
2125 return LOG_EMBEDDER_ERROR(
2127 "Could not infer the Flutter project to run from given arguments.");
2128 }
2129
2130 // Create the engine but don't launch the shell or run the root isolate.
2131 auto embedder_engine = std::make_unique<flutter::EmbedderEngine>(
2132 std::move(thread_host), //
2133 std::move(task_runners), //
2134 std::move(settings), //
2135 std::move(run_configuration), //
2136 on_create_platform_view, //
2137 on_create_rasterizer, //
2138 std::move(external_texture_resolver) //
2139 );
2140
2141 // Release the ownership of the embedder engine to the caller.
2142 *engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(
2143 embedder_engine.release());
2144 return kSuccess;
2145}
2146
2149 if (!engine) {
2150 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2151 }
2152
2153 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2154
2155 // The engine must not already be running. Initialize may only be called
2156 // once on an engine instance.
2157 if (embedder_engine->IsValid()) {
2158 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2159 }
2160
2161 // Step 1: Launch the shell.
2162 if (!embedder_engine->LaunchShell()) {
2164 "Could not launch the engine using supplied "
2165 "initialization arguments.");
2166 }
2167
2168 // Step 2: Tell the platform view to initialize itself.
2169 if (!embedder_engine->NotifyCreated()) {
2171 "Could not create platform view components.");
2172 }
2173
2174 // Step 3: Launch the root isolate.
2175 if (!embedder_engine->RunRootIsolate()) {
2176 return LOG_EMBEDDER_ERROR(
2178 "Could not run the root isolate of the Flutter application using the "
2179 "project arguments specified.");
2180 }
2181
2182 return kSuccess;
2183}
2184
2187 engine,
2188 const FlutterAddViewInfo* info) {
2189 if (!engine) {
2190 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2191 }
2192 if (!info || !info->view_metrics || !info->add_view_callback) {
2194 "Add view info handle was invalid.");
2195 }
2196
2197 FlutterViewId view_id = info->view_id;
2198 if (view_id == kFlutterImplicitViewId) {
2199 return LOG_EMBEDDER_ERROR(
2201 "Add view info was invalid. The implicit view cannot be added.");
2202 }
2203 if (SAFE_ACCESS(info->view_metrics, view_id, kFlutterImplicitViewId) !=
2204 view_id) {
2205 if (view_id == kFlutterImplicitViewId) {
2207 "Add view info was invalid. The info and "
2208 "window metric view IDs must match.");
2209 }
2210 }
2211
2212 // TODO(loicsharma): Return an error if the engine was initialized with
2213 // callbacks that are incompatible with multiple views.
2214 // https://github.com/flutter/flutter/issues/144806
2215
2216 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2218
2219 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2220 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2221 }
2222
2223 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2224
2225 // The engine must be running to add a view.
2226 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2227 if (!embedder_engine->IsValid()) {
2228 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2229 }
2230
2232 [c_callback = info->add_view_callback,
2233 user_data = info->user_data](bool added) {
2236 result.added = added;
2237 result.user_data = user_data;
2238 c_callback(&result);
2239 };
2240
2241 embedder_engine->GetShell().GetPlatformView()->AddView(view_id, metrics,
2242 callback);
2243 return kSuccess;
2244}
2245
2248 engine,
2249 const FlutterRemoveViewInfo* info) {
2250 if (!engine) {
2251 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2252 }
2253 if (!info || !info->remove_view_callback) {
2255 "Remove view info handle was invalid.");
2256 }
2257
2258 if (info->view_id == kFlutterImplicitViewId) {
2259 return LOG_EMBEDDER_ERROR(
2261 "Remove view info was invalid. The implicit view cannot be removed.");
2262 }
2263
2264 // TODO(loicsharma): Return an error if the engine was initialized with
2265 // callbacks that are incompatible with multiple views.
2266 // https://github.com/flutter/flutter/issues/144806
2267
2268 // The engine must be running to remove a view.
2269 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2270 if (!embedder_engine->IsValid()) {
2271 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2272 }
2273
2275 [c_callback = info->remove_view_callback,
2276 user_data = info->user_data](bool removed) {
2279 result.removed = removed;
2280 result.user_data = user_data;
2281 c_callback(&result);
2282 };
2283
2284 embedder_engine->GetShell().GetPlatformView()->RemoveView(info->view_id,
2285 callback);
2286 return kSuccess;
2287}
2288
2291 engine) {
2292 if (engine == nullptr) {
2293 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2294 }
2295
2296 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2297 embedder_engine->NotifyDestroyed();
2298 embedder_engine->CollectShell();
2299 return kSuccess;
2300}
2301
2303 engine) {
2305 if (result != kSuccess) {
2306 return result;
2307 }
2308 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2309 delete embedder_engine;
2310 return kSuccess;
2311}
2312
2315 const FlutterWindowMetricsEvent* flutter_metrics) {
2316 if (engine == nullptr || flutter_metrics == nullptr) {
2317 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2318 }
2319 FlutterViewId view_id =
2320 SAFE_ACCESS(flutter_metrics, view_id, kFlutterImplicitViewId);
2321
2322 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2323 MakeViewportMetricsFromWindowMetrics(flutter_metrics);
2324 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2325 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2326 }
2327
2328 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2329
2330 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
2331 view_id, metrics)
2332 ? kSuccess
2334 "Viewport metrics were invalid.");
2335}
2336
2337// Returns the flutter::PointerData::Change for the given FlutterPointerPhase.
2339 FlutterPointerPhase phase) {
2340 switch (phase) {
2341 case kCancel:
2343 case kUp:
2345 case kDown:
2347 case kMove:
2349 case kAdd:
2351 case kRemove:
2353 case kHover:
2355 case kPanZoomStart:
2357 case kPanZoomUpdate:
2359 case kPanZoomEnd:
2361 }
2363}
2364
2365// Returns the flutter::PointerData::DeviceKind for the given
2366// FlutterPointerDeviceKind.
2368 FlutterPointerDeviceKind device_kind) {
2369 switch (device_kind) {
2378 }
2380}
2381
2382// Returns the flutter::PointerData::SignalKind for the given
2383// FlutterPointerSignaKind.
2386 switch (kind) {
2395 }
2397}
2398
2399// Returns the buttons to synthesize for a PointerData from a
2400// FlutterPointerEvent with no type or buttons set.
2403 switch (change) {
2406 // These kinds of change must have a non-zero `buttons`, otherwise
2407 // gesture recognizers will ignore these events.
2417 return 0;
2418 }
2419 return 0;
2420}
2421
2424 const FlutterPointerEvent* pointers,
2425 size_t events_count) {
2426 if (engine == nullptr) {
2427 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2428 }
2429
2430 if (pointers == nullptr || events_count == 0) {
2431 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid pointer events.");
2432 }
2433
2434 auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
2435
2436 const FlutterPointerEvent* current = pointers;
2437
2438 for (size_t i = 0; i < events_count; ++i) {
2439 flutter::PointerData pointer_data;
2440 pointer_data.Clear();
2441 // this is currely in use only on android embedding.
2442 pointer_data.embedder_id = 0;
2443 pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
2444 pointer_data.change = ToPointerDataChange(
2445 SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
2446 pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
2447 pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
2448 // Delta will be generated in pointer_data_packet_converter.cc.
2449 pointer_data.physical_delta_x = 0.0;
2450 pointer_data.physical_delta_y = 0.0;
2451 pointer_data.device = SAFE_ACCESS(current, device, 0);
2452 // Pointer identifier will be generated in
2453 // pointer_data_packet_converter.cc.
2454 pointer_data.pointer_identifier = 0;
2455 pointer_data.signal_kind = ToPointerDataSignalKind(
2456 SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
2457 pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
2458 pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
2459 FlutterPointerDeviceKind device_kind =
2460 SAFE_ACCESS(current, device_kind, kFlutterPointerDeviceKindMouse);
2461 // For backwards compatibility with embedders written before the device
2462 // kind and buttons were exposed, if the device kind is not set treat it
2463 // as a mouse, with a synthesized primary button state based on the phase.
2464 if (device_kind == 0) {
2466 pointer_data.buttons =
2468
2469 } else {
2470 pointer_data.kind = ToPointerDataKind(device_kind);
2471 if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
2472 // For touch events, set the button internally rather than requiring
2473 // it at the API level, since it's a confusing construction to expose.
2474 if (pointer_data.change == flutter::PointerData::Change::kDown ||
2477 }
2478 } else {
2479 // Buttons use the same mask values, so pass them through directly.
2480 pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
2481 }
2482 }
2483 pointer_data.pan_x = SAFE_ACCESS(current, pan_x, 0.0);
2484 pointer_data.pan_y = SAFE_ACCESS(current, pan_y, 0.0);
2485 // Delta will be generated in pointer_data_packet_converter.cc.
2486 pointer_data.pan_delta_x = 0.0;
2487 pointer_data.pan_delta_y = 0.0;
2488 pointer_data.scale = SAFE_ACCESS(current, scale, 0.0);
2489 pointer_data.rotation = SAFE_ACCESS(current, rotation, 0.0);
2490 pointer_data.view_id =
2491 SAFE_ACCESS(current, view_id, kFlutterImplicitViewId);
2492 packet->SetPointerData(i, pointer_data);
2493 current = reinterpret_cast<const FlutterPointerEvent*>(
2494 reinterpret_cast<const uint8_t*>(current) + current->struct_size);
2495 }
2496
2497 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2498 ->DispatchPointerDataPacket(std::move(packet))
2499 ? kSuccess
2501 "Could not dispatch pointer events to the "
2502 "running Flutter application.");
2503}
2504
2506 FlutterKeyEventType event_kind) {
2507 switch (event_kind) {
2514 }
2516}
2517
2519 FlutterKeyEventDeviceType event_kind) {
2520 switch (event_kind) {
2531 }
2533}
2534
2535// Send a platform message to the framework.
2536//
2537// The `data_callback` will be invoked with `user_data`, and must not be empty.
2540 const char* channel,
2541 const uint8_t* data,
2542 size_t size,
2543 FlutterDataCallback data_callback,
2544 void* user_data) {
2546
2547 FlutterPlatformMessageResponseHandle* response_handle;
2549 engine, data_callback, user_data, &response_handle);
2550 if (result != kSuccess) {
2551 return result;
2552 }
2553
2555 sizeof(FlutterPlatformMessage), // struct_size
2556 channel, // channel
2557 data, // message
2558 size, // message_size
2559 response_handle, // response_handle
2560 };
2561
2563 // Whether `SendPlatformMessage` succeeds or not, the response handle must be
2564 // released.
2565 FlutterEngineResult release_result =
2567 if (result != kSuccess) {
2568 return result;
2569 }
2570
2571 return release_result;
2572}
2573
2575 engine,
2576 const FlutterKeyEvent* event,
2578 void* user_data) {
2579 if (engine == nullptr) {
2580 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2581 }
2582
2583 if (event == nullptr) {
2584 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid key event.");
2585 }
2586
2587 const char* character = SAFE_ACCESS(event, character, nullptr);
2588
2589 flutter::KeyData key_data;
2590 key_data.Clear();
2591 key_data.timestamp = static_cast<uint64_t>(SAFE_ACCESS(event, timestamp, 0));
2592 key_data.type = MapKeyEventType(
2594 key_data.physical = SAFE_ACCESS(event, physical, 0);
2595 key_data.logical = SAFE_ACCESS(event, logical, 0);
2596 key_data.synthesized = SAFE_ACCESS(event, synthesized, false);
2598 event, device_type,
2600
2601 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data, character);
2602
2603 struct MessageData {
2605 void* user_data;
2606 };
2607
2608 MessageData* message_data =
2609 new MessageData{.callback = callback, .user_data = user_data};
2610
2612 engine, kFlutterKeyDataChannel, packet->data().data(),
2613 packet->data().size(),
2614 [](const uint8_t* data, size_t size, void* user_data) {
2615 auto message_data = std::unique_ptr<MessageData>(
2616 reinterpret_cast<MessageData*>(user_data));
2617 if (message_data->callback == nullptr) {
2618 return;
2619 }
2620 bool handled = false;
2621 if (size == 1) {
2622 handled = *data != 0;
2623 }
2624 message_data->callback(handled, message_data->user_data);
2625 },
2626 message_data);
2627}
2628
2631 const FlutterPlatformMessage* flutter_message) {
2632 if (engine == nullptr) {
2633 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2634 }
2635
2636 if (flutter_message == nullptr) {
2637 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid message argument.");
2638 }
2639
2640 if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
2641 return LOG_EMBEDDER_ERROR(
2642 kInvalidArguments, "Message argument did not specify a valid channel.");
2643 }
2644
2645 size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
2646 const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
2647
2648 if (message_size != 0 && message_data == nullptr) {
2649 return LOG_EMBEDDER_ERROR(
2651 "Message size was non-zero but the message data was nullptr.");
2652 }
2653
2654 const FlutterPlatformMessageResponseHandle* response_handle =
2655 SAFE_ACCESS(flutter_message, response_handle, nullptr);
2656
2658 if (response_handle && response_handle->message) {
2659 response = response_handle->message->response();
2660 }
2661
2662 std::unique_ptr<flutter::PlatformMessage> message;
2663 if (message_size == 0) {
2664 message = std::make_unique<flutter::PlatformMessage>(
2665 flutter_message->channel, response);
2666 } else {
2667 message = std::make_unique<flutter::PlatformMessage>(
2668 flutter_message->channel,
2669 fml::MallocMapping::Copy(message_data, message_size), response);
2670 }
2671
2672 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2673 ->SendPlatformMessage(std::move(message))
2674 ? kSuccess
2676 "Could not send a message to the running "
2677 "Flutter application.");
2678}
2679
2682 FlutterDataCallback data_callback,
2683 void* user_data,
2684 FlutterPlatformMessageResponseHandle** response_out) {
2685 if (engine == nullptr) {
2686 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2687 }
2688
2689 if (data_callback == nullptr || response_out == nullptr) {
2690 return LOG_EMBEDDER_ERROR(
2691 kInvalidArguments, "Data callback or the response handle was invalid.");
2692 }
2693
2695 [user_data, data_callback](const uint8_t* data, size_t size) {
2696 data_callback(data, size, user_data);
2697 };
2698
2699 auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
2700 ->GetTaskRunners()
2701 .GetPlatformTaskRunner();
2702
2703 auto handle = new FlutterPlatformMessageResponseHandle();
2704
2705 handle->message = std::make_unique<flutter::PlatformMessage>(
2706 "", // The channel is empty and unused as the response handle is going
2707 // to referenced directly in the |FlutterEngineSendPlatformMessage|
2708 // with the container message discarded.
2709 fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
2710 std::move(platform_task_runner), response_callback));
2711 *response_out = handle;
2712 return kSuccess;
2713}
2714
2718 if (engine == nullptr) {
2719 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2720 }
2721
2722 if (response == nullptr) {
2723 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid response handle.");
2724 }
2725 delete response;
2726 return kSuccess;
2727}
2728
2729// Note: This can execute on any thread.
2733 const uint8_t* data,
2734 size_t data_length) {
2735 if (data_length != 0 && data == nullptr) {
2736 return LOG_EMBEDDER_ERROR(
2738 "Data size was non zero but the pointer to the data was null.");
2739 }
2740
2741 auto response = handle->message->response();
2742
2743 if (response) {
2744 if (data_length == 0) {
2745 response->CompleteEmpty();
2746 } else {
2747 response->Complete(std::make_unique<fml::DataMapping>(
2748 std::vector<uint8_t>({data, data + data_length})));
2749 }
2750 }
2751
2752 delete handle;
2753
2754 return kSuccess;
2755}
2756
2759 return kSuccess;
2760}
2761
2764 int64_t texture_identifier) {
2765 if (engine == nullptr) {
2766 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2767 }
2768
2769 if (texture_identifier == 0) {
2771 "Texture identifier was invalid.");
2772 }
2773 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
2774 texture_identifier)) {
2776 "Could not register the specified texture.");
2777 }
2778 return kSuccess;
2779}
2780
2783 int64_t texture_identifier) {
2784 if (engine == nullptr) {
2785 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2786 }
2787
2788 if (texture_identifier == 0) {
2790 "Texture identifier was invalid.");
2791 }
2792
2793 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
2794 texture_identifier)) {
2796 "Could not un-register the specified texture.");
2797 }
2798
2799 return kSuccess;
2800}
2801
2804 int64_t texture_identifier) {
2805 if (engine == nullptr) {
2806 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2807 }
2808 if (texture_identifier == 0) {
2809 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid texture identifier.");
2810 }
2811 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2812 ->MarkTextureFrameAvailable(texture_identifier)) {
2813 return LOG_EMBEDDER_ERROR(
2815 "Could not mark the texture frame as being available.");
2816 }
2817 return kSuccess;
2818}
2819
2822 bool enabled) {
2823 if (engine == nullptr) {
2824 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2825 }
2826 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetSemanticsEnabled(
2827 enabled)) {
2829 "Could not update semantics state.");
2830 }
2831 return kSuccess;
2832}
2833
2837 if (engine == nullptr) {
2838 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2839 }
2840 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2841 ->SetAccessibilityFeatures(flags)) {
2843 "Could not update accessibility features.");
2844 }
2845 return kSuccess;
2846}
2847
2850 uint64_t node_id,
2852 const uint8_t* data,
2853 size_t data_length) {
2854 if (engine == nullptr) {
2855 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2856 }
2857 auto engine_action = static_cast<flutter::SemanticsAction>(action);
2858 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2860 node_id, engine_action,
2861 fml::MallocMapping::Copy(data, data_length))) {
2863 "Could not dispatch semantics action.");
2864 }
2865 return kSuccess;
2866}
2867
2869 engine,
2870 intptr_t baton,
2871 uint64_t frame_start_time_nanos,
2872 uint64_t frame_target_time_nanos) {
2873 if (engine == nullptr) {
2874 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2875 }
2876
2877 TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
2878
2879 auto start_time = fml::TimePoint::FromEpochDelta(
2880 fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
2881
2882 auto target_time = fml::TimePoint::FromEpochDelta(
2883 fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
2884
2885 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
2886 baton, start_time, target_time)) {
2887 return LOG_EMBEDDER_ERROR(
2889 "Could not notify the running engine instance of a Vsync event.");
2890 }
2891
2892 return kSuccess;
2893}
2894
2897 if (engine == nullptr) {
2898 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2899 }
2900
2901 TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
2902
2903 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2904 ->ReloadSystemFonts()) {
2906 "Could not reload system fonts.");
2907 }
2908
2909 return kSuccess;
2910}
2911
2913 fml::tracing::TraceEvent0("flutter", name, /*flow_id_count=*/0,
2914 /*flow_ids=*/nullptr);
2915}
2916
2917void FlutterEngineTraceEventDurationEnd(const char* name) {
2919}
2920
2921void FlutterEngineTraceEventInstant(const char* name) {
2922 fml::tracing::TraceEventInstant0("flutter", name, /*flow_id_count=*/0,
2923 /*flow_ids=*/nullptr);
2924}
2925
2929 void* baton) {
2930 if (engine == nullptr) {
2931 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2932 }
2933
2934 if (callback == nullptr) {
2936 "Render thread callback was null.");
2937 }
2938
2939 auto task = [callback, baton]() { callback(baton); };
2940
2941 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2942 ->PostRenderThreadTask(task)
2943 ? kSuccess
2945 "Could not post the render thread task.");
2946}
2947
2948uint64_t FlutterEngineGetCurrentTime() {
2950}
2951
2953 engine,
2954 const FlutterTask* task) {
2955 if (engine == nullptr) {
2956 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2957 }
2958
2959 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
2960 ? kSuccess
2962 "Could not run the specified task.");
2963}
2964
2966 engine,
2967 const rapidjson::Document& document,
2968 const std::string& channel_name) {
2969 if (channel_name.empty()) {
2970 return false;
2971 }
2972
2973 rapidjson::StringBuffer buffer;
2974 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
2975
2976 if (!document.Accept(writer)) {
2977 return false;
2978 }
2979
2980 const char* message = buffer.GetString();
2981
2982 if (message == nullptr || buffer.GetSize() == 0) {
2983 return false;
2984 }
2985
2986 auto platform_message = std::make_unique<flutter::PlatformMessage>(
2987 channel_name.c_str(), // channel
2989 buffer.GetSize()), // message
2990 nullptr // response
2991 );
2992
2993 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2994 ->SendPlatformMessage(std::move(platform_message));
2995}
2996
2998 engine,
2999 const FlutterLocale** locales,
3000 size_t locales_count) {
3001 if (engine == nullptr) {
3002 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3003 }
3004
3005 if (locales_count == 0) {
3006 return kSuccess;
3007 }
3008
3009 if (locales == nullptr) {
3010 return LOG_EMBEDDER_ERROR(kInvalidArguments, "No locales were specified.");
3011 }
3012
3013 rapidjson::Document document;
3014 auto& allocator = document.GetAllocator();
3015
3016 document.SetObject();
3017 document.AddMember("method", "setLocale", allocator);
3018
3019 rapidjson::Value args(rapidjson::kArrayType);
3020 args.Reserve(locales_count * 4, allocator);
3021 for (size_t i = 0; i < locales_count; ++i) {
3022 const FlutterLocale* locale = locales[i];
3023 const char* language_code_str = SAFE_ACCESS(locale, language_code, nullptr);
3024 if (language_code_str == nullptr || ::strlen(language_code_str) == 0) {
3025 return LOG_EMBEDDER_ERROR(
3027 "Language code is required but not present in FlutterLocale.");
3028 }
3029
3030 const char* country_code_str = SAFE_ACCESS(locale, country_code, "");
3031 const char* script_code_str = SAFE_ACCESS(locale, script_code, "");
3032 const char* variant_code_str = SAFE_ACCESS(locale, variant_code, "");
3033
3034 rapidjson::Value language_code, country_code, script_code, variant_code;
3035
3036 language_code.SetString(language_code_str, allocator);
3037 country_code.SetString(country_code_str ? country_code_str : "", allocator);
3038 script_code.SetString(script_code_str ? script_code_str : "", allocator);
3039 variant_code.SetString(variant_code_str ? variant_code_str : "", allocator);
3040
3041 // Required.
3042 args.PushBack(language_code, allocator);
3043 args.PushBack(country_code, allocator);
3044 args.PushBack(script_code, allocator);
3045 args.PushBack(variant_code, allocator);
3046 }
3047 document.AddMember("args", args, allocator);
3048
3049 return DispatchJSONPlatformMessage(engine, document, "flutter/localization")
3050 ? kSuccess
3052 "Could not send message to update locale of "
3053 "a running Flutter application.");
3054}
3055
3058}
3059
3063 const FlutterEngineDartObject* object) {
3064 if (engine == nullptr) {
3065 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3066 }
3067
3068 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->IsValid()) {
3069 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine not running.");
3070 }
3071
3072 if (port == ILLEGAL_PORT) {
3074 "Attempted to post to an illegal port.");
3075 }
3076
3077 if (object == nullptr) {
3079 "Invalid Dart object to post.");
3080 }
3081
3082 Dart_CObject dart_object = {};
3083 fml::ScopedCleanupClosure typed_data_finalizer;
3084
3085 switch (object->type) {
3087 dart_object.type = Dart_CObject_kNull;
3088 break;
3090 dart_object.type = Dart_CObject_kBool;
3091 dart_object.value.as_bool = object->bool_value;
3092 break;
3094 dart_object.type = Dart_CObject_kInt32;
3095 dart_object.value.as_int32 = object->int32_value;
3096 break;
3098 dart_object.type = Dart_CObject_kInt64;
3099 dart_object.value.as_int64 = object->int64_value;
3100 break;
3102 dart_object.type = Dart_CObject_kDouble;
3103 dart_object.value.as_double = object->double_value;
3104 break;
3106 if (object->string_value == nullptr) {
3108 "kFlutterEngineDartObjectTypeString must be "
3109 "a null terminated string but was null.");
3110 }
3111 dart_object.type = Dart_CObject_kString;
3112 dart_object.value.as_string = const_cast<char*>(object->string_value);
3113 break;
3115 auto* buffer = SAFE_ACCESS(object->buffer_value, buffer, nullptr);
3116 if (buffer == nullptr) {
3118 "kFlutterEngineDartObjectTypeBuffer must "
3119 "specify a buffer but found nullptr.");
3120 }
3121 auto buffer_size = SAFE_ACCESS(object->buffer_value, buffer_size, 0);
3122 auto callback =
3123 SAFE_ACCESS(object->buffer_value, buffer_collect_callback, nullptr);
3124 auto user_data = SAFE_ACCESS(object->buffer_value, user_data, nullptr);
3125
3126 // The user has provided a callback, let them manage the lifecycle of
3127 // the underlying data. If not, copy it out from the provided buffer.
3128
3129 if (callback == nullptr) {
3130 dart_object.type = Dart_CObject_kTypedData;
3132 dart_object.value.as_typed_data.length = buffer_size;
3133 dart_object.value.as_typed_data.values = buffer;
3134 } else {
3135 struct ExternalTypedDataPeer {
3136 void* user_data = nullptr;
3137 VoidCallback trampoline = nullptr;
3138 };
3139 auto peer = new ExternalTypedDataPeer();
3140 peer->user_data = user_data;
3141 peer->trampoline = callback;
3142 // This finalizer is set so that in case of failure of the
3143 // Dart_PostCObject below, we collect the peer. The embedder is still
3144 // responsible for collecting the buffer in case of non-kSuccess
3145 // returns from this method. This finalizer must be released in case
3146 // of kSuccess returns from this method.
3147 typed_data_finalizer.SetClosure([peer]() {
3148 // This is the tiny object we use as the peer to the Dart call so
3149 // that we can attach the a trampoline to the embedder supplied
3150 // callback. In case of error, we need to collect this object lest
3151 // we introduce a tiny leak.
3152 delete peer;
3153 });
3158 dart_object.value.as_external_typed_data.peer = peer;
3160 +[](void* unused_isolate_callback_data, void* peer) {
3161 auto typed_peer = reinterpret_cast<ExternalTypedDataPeer*>(peer);
3162 typed_peer->trampoline(typed_peer->user_data);
3163 delete typed_peer;
3164 };
3165 }
3166 } break;
3167 default:
3168 return LOG_EMBEDDER_ERROR(
3170 "Invalid FlutterEngineDartObjectType type specified.");
3171 }
3172
3173 if (!Dart_PostCObject(port, &dart_object)) {
3175 "Could not post the object to the Dart VM.");
3176 }
3177
3178 // On a successful call, the VM takes ownership of and is responsible for
3179 // invoking the finalizer.
3180 typed_data_finalizer.Release();
3181 return kSuccess;
3182}
3183
3185 FLUTTER_API_SYMBOL(FlutterEngine) raw_engine) {
3186 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3187 if (engine == nullptr || !engine->IsValid()) {
3188 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine was invalid.");
3189 }
3190
3191 engine->GetShell().NotifyLowMemoryWarning();
3192
3193 rapidjson::Document document;
3194 auto& allocator = document.GetAllocator();
3195
3196 document.SetObject();
3197 document.AddMember("type", "memoryPressure", allocator);
3198
3199 return DispatchJSONPlatformMessage(raw_engine, document, "flutter/system")
3200 ? kSuccess
3203 "Could not dispatch the low memory notification message.");
3204}
3205
3209 void* user_data) {
3210 if (engine == nullptr) {
3211 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3212 }
3213
3214 if (callback == nullptr) {
3216 "Invalid native thread callback.");
3217 }
3218
3219 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3220 ->PostTaskOnEngineManagedNativeThreads(
3223 })
3224 ? kSuccess
3226 "Internal error while attempting to post "
3227 "tasks to all threads.");
3228}
3229
3230namespace {
3231static bool ValidDisplayConfiguration(const FlutterEngineDisplay* displays,
3232 size_t display_count) {
3233 std::set<FlutterEngineDisplayId> display_ids;
3234 for (size_t i = 0; i < display_count; i++) {
3235 if (displays[i].single_display && display_count != 1) {
3236 return false;
3237 }
3238 display_ids.insert(displays[i].display_id);
3239 }
3240
3241 return display_ids.size() == display_count;
3242}
3243} // namespace
3244
3247 const FlutterEngineDisplaysUpdateType update_type,
3248 const FlutterEngineDisplay* embedder_displays,
3249 size_t display_count) {
3250 if (raw_engine == nullptr) {
3251 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3252 }
3253
3254 if (!ValidDisplayConfiguration(embedder_displays, display_count)) {
3255 return LOG_EMBEDDER_ERROR(
3257 "Invalid FlutterEngineDisplay configuration specified.");
3258 }
3259
3260 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3261
3262 switch (update_type) {
3264 std::vector<std::unique_ptr<flutter::Display>> displays;
3265 const auto* display = embedder_displays;
3266 for (size_t i = 0; i < display_count; i++) {
3267 displays.push_back(std::make_unique<flutter::Display>(
3268 SAFE_ACCESS(display, display_id, i), //
3269 SAFE_ACCESS(display, refresh_rate, 0), //
3270 SAFE_ACCESS(display, width, 0), //
3271 SAFE_ACCESS(display, height, 0), //
3272 SAFE_ACCESS(display, device_pixel_ratio, 1)));
3273 display = reinterpret_cast<const FlutterEngineDisplay*>(
3274 reinterpret_cast<const uint8_t*>(display) + display->struct_size);
3275 }
3276 engine->GetShell().OnDisplayUpdates(std::move(displays));
3277 return kSuccess;
3278 }
3279 default:
3280 return LOG_EMBEDDER_ERROR(
3282 "Invalid FlutterEngineDisplaysUpdateType type specified.");
3283 }
3284}
3285
3287 engine) {
3288 if (engine == nullptr) {
3289 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3290 }
3291
3292 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->ScheduleFrame()
3293 ? kSuccess
3295 "Could not schedule frame.");
3296}
3297
3301 void* user_data) {
3302 if (engine == nullptr) {
3303 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3304 }
3305
3306 if (callback == nullptr) {
3308 "Next frame callback was null.");
3309 }
3310
3311 flutter::EmbedderEngine* embedder_engine =
3312 reinterpret_cast<flutter::EmbedderEngine*>(engine);
3313
3314 fml::WeakPtr<flutter::PlatformView> weak_platform_view =
3315 embedder_engine->GetShell().GetPlatformView();
3316
3317 if (!weak_platform_view) {
3319 "Platform view unavailable.");
3320 }
3321
3322 weak_platform_view->SetNextFrameCallback(
3324
3325 return kSuccess;
3326}
3327
3330 if (!table) {
3331 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null table specified.");
3332 }
3333#define SET_PROC(member, function) \
3334 if (STRUCT_HAS_MEMBER(table, member)) { \
3335 table->member = &function; \
3336 }
3337
3338 SET_PROC(CreateAOTData, FlutterEngineCreateAOTData);
3339 SET_PROC(CollectAOTData, FlutterEngineCollectAOTData);
3342 SET_PROC(Initialize, FlutterEngineInitialize);
3343 SET_PROC(Deinitialize, FlutterEngineDeinitialize);
3344 SET_PROC(RunInitialized, FlutterEngineRunInitialized);
3345 SET_PROC(SendWindowMetricsEvent, FlutterEngineSendWindowMetricsEvent);
3346 SET_PROC(SendPointerEvent, FlutterEngineSendPointerEvent);
3347 SET_PROC(SendKeyEvent, FlutterEngineSendKeyEvent);
3348 SET_PROC(SendPlatformMessage, FlutterEngineSendPlatformMessage);
3349 SET_PROC(PlatformMessageCreateResponseHandle,
3351 SET_PROC(PlatformMessageReleaseResponseHandle,
3353 SET_PROC(SendPlatformMessageResponse,
3355 SET_PROC(RegisterExternalTexture, FlutterEngineRegisterExternalTexture);
3356 SET_PROC(UnregisterExternalTexture, FlutterEngineUnregisterExternalTexture);
3357 SET_PROC(MarkExternalTextureFrameAvailable,
3359 SET_PROC(UpdateSemanticsEnabled, FlutterEngineUpdateSemanticsEnabled);
3360 SET_PROC(UpdateAccessibilityFeatures,
3362 SET_PROC(DispatchSemanticsAction, FlutterEngineDispatchSemanticsAction);
3364 SET_PROC(ReloadSystemFonts, FlutterEngineReloadSystemFonts);
3365 SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin);
3366 SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd);
3367 SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant);
3368 SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask);
3371 SET_PROC(UpdateLocales, FlutterEngineUpdateLocales);
3372 SET_PROC(RunsAOTCompiledDartCode, FlutterEngineRunsAOTCompiledDartCode);
3373 SET_PROC(PostDartObject, FlutterEnginePostDartObject);
3374 SET_PROC(NotifyLowMemoryWarning, FlutterEngineNotifyLowMemoryWarning);
3375 SET_PROC(PostCallbackOnAllNativeThreads,
3377 SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate);
3378 SET_PROC(ScheduleFrame, FlutterEngineScheduleFrame);
3379 SET_PROC(SetNextFrameCallback, FlutterEngineSetNextFrameCallback);
3381 SET_PROC(RemoveView, FlutterEngineRemoveView);
3382#undef SET_PROC
3383
3384 return kSuccess;
3385}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
@ kBottomLeft_GrSurfaceOrigin
Definition GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kUnknown_SkPixelGeometry
SI F table(const skcms_Curve *curve, F v)
static sk_sp< SkColorSpace > MakeSRGB()
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
Definition SkMatrix.h:179
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:205
bool DispatchSemanticsAction(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
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(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(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions)> UpdateSemanticsCallback
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...
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
Definition shell.h:119
fml::WeakPtr< PlatformView > GetPlatformView()
Platform views may only be accessed on the platform task runner.
Definition shell.cc:818
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:54
fml::closure Release()
Definition closure.h:60
@ 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
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(ReactorGLES::Ref reactor, TextureDescriptor desc, GLuint fbo)
#define ILLEGAL_PORT
Definition dart_api.h:1530
@ Dart_TypedData_kUint8
Definition dart_api.h:2606
@ Dart_CObject_kInt64
@ Dart_CObject_kDouble
@ Dart_CObject_kTypedData
@ Dart_CObject_kString
@ Dart_CObject_kNull
@ Dart_CObject_kExternalTypedData
@ Dart_CObject_kInt32
@ Dart_CObject_kBool
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject *message)
SkRect sk_rect
#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:2922
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:2539
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:2803
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 engine via the FlutterTa...
Definition embedder.cc:2953
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:2869
const int32_t kFlutterSemanticsNodeIdBatchEnd
Definition embedder.cc:104
const int32_t kFlutterSemanticsCustomActionIdBatchEnd
Definition embedder.cc:105
static bool IsMetalRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:188
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:1711
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:2763
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:2998
const uint8_t kPlatformStrongDill[]
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)
Definition embedder.cc:707
FlutterEngineResult FlutterEngineGetProcAddresses(FlutterEngineProcTable *table)
Gets the table of engine function pointers.
Definition embedder.cc:3329
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)
Definition embedder.cc:583
static bool DispatchJSONPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const rapidjson::Document &document, const std::string &channel_name)
Definition embedder.cc:2966
FlutterEngineResult FlutterEngineScheduleFrame(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Schedule a new frame to redraw the content.
Definition embedder.cc:3287
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:2913
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:2314
flutter::PointerData::SignalKind ToPointerDataSignalKind(FlutterPointerSignalKind kind)
Definition embedder.cc:2385
static std::pair< std::unique_ptr< flutter::EmbedderExternalViewEmbedder >, bool > InferExternalViewEmbedderFromArgs(const FlutterCompositor *compositor, bool enable_impeller)
Definition embedder.cc:1279
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:2949
static bool IsOpenGLRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:155
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:3299
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:2758
#define LOG_EMBEDDER_ERROR(code, reason)
Definition embedder.cc:152
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:2927
static flutter::KeyEventDeviceType MapKeyEventDeviceType(FlutterKeyEventDeviceType event_kind)
Definition embedder.cc:2519
static bool IsRendererValid(const FlutterRendererConfig *config)
Definition embedder.cc:226
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:961
std::unique_ptr< Dart_LoadedElf, LoadedElfDeleter > UniqueLoadedElf
Definition embedder.cc:1412
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.
Definition embedder.cc:2849
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:3061
flutter::PointerData::DeviceKind ToPointerDataKind(FlutterPointerDeviceKind device_kind)
Definition embedder.cc:2368
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:2291
static sk_sp< SkSurface > MakeSkSurfaceFromBackingStore(GrDirectContext *context, const FlutterBackingStoreConfig &config, const FlutterOpenGLTexture *texture)
Definition embedder.cc:742
flutter::PointerData::Change ToPointerDataChange(FlutterPointerPhase phase)
Definition embedder.cc:2339
static constexpr FlutterViewId kFlutterImplicitViewId
Definition embedder.cc:107
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:3207
FLUTTER_EXPORT FlutterEngineResult FlutterEngineAddView(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterAddViewInfo *info)
Adds a view.
Definition embedder.cc:2187
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:1727
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:1163
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV3(FlutterUpdateSemanticsCallback2 update_semantics_callback, void *user_data)
Definition embedder.cc:1649
FlutterEngineResult FlutterEngineUpdateAccessibilityFeatures(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterAccessibilityFeature flags)
Sets additional accessibility features.
Definition embedder.cc:2835
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:2303
static std::unique_ptr< flutter::EmbedderRenderTarget > MakeRenderTargetFromSkSurface(FlutterBackingStore backing_store, sk_sp< SkSurface > skia_surface, fml::closure on_release)
Definition embedder.cc:1152
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:2681
FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data)
Collects the AOT data.
Definition embedder.cc:1476
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:3246
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition embedder.cc:2630
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition embedder.cc:3057
FlutterEngineResult FlutterEngineReloadSystemFonts(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Reloads the system fonts in engine.
Definition embedder.cc:2896
static flutter::KeyEventType MapKeyEventType(FlutterKeyEventType event_kind)
Definition embedder.cc:2506
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallback(const FlutterProjectArgs *args, void *user_data)
Definition embedder.cc:1665
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:670
const intptr_t kPlatformStrongDillSize
#define FLUTTER_EXPORT
Definition embedder.cc:31
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV1(FlutterUpdateSemanticsNodeCallback update_semantics_node_callback, FlutterUpdateSemanticsCustomActionCallback update_semantics_custom_action_callback, void *user_data)
Definition embedder.cc:1585
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition embedder.cc:2423
FlutterEngineResult FlutterEngineRunInitialized(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Runs an initialized engine instance. An engine can be initialized via FlutterEngineInitialize....
Definition embedder.cc:2148
static bool IsSoftwareRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:173
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)
Definition embedder.cc:283
void PopulateJITSnapshotMappingCallbacks(const FlutterProjectArgs *args, flutter::Settings &settings)
Definition embedder.cc:1489
static bool IsVulkanRendererConfigValid(const FlutterRendererConfig *config)
Definition embedder.cc:206
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:3185
FlutterEngineResult FlutterEngineUnregisterExternalTexture(FLUTTER_API_SYMBOL(FlutterEngine) engine, int64_t texture_identifier)
Unregister a previous texture registration.
Definition embedder.cc:2782
FlutterEngineResult FlutterEngineUpdateSemanticsEnabled(FLUTTER_API_SYMBOL(FlutterEngine) engine, bool enabled)
Enable or disable accessibility semantics.
Definition embedder.cc:2821
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:2575
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)
Definition embedder.cc:495
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:2918
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:2731
const char * kFlutterKeyDataChannel
Definition embedder.cc:129
FLUTTER_EXPORT FlutterEngineResult FlutterEngineRemoveView(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterRemoveViewInfo *info)
Removes a view.
Definition embedder.cc:2248
int64_t PointerDataButtonsForLegacyEvent(flutter::PointerData::Change change)
Definition embedder.cc:2402
void PopulateAOTSnapshotMappingCallbacks(const FlutterProjectArgs *args, flutter::Settings &settings)
Definition embedder.cc:1532
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
Definition embedder.cc:2716
flutter::PlatformViewEmbedder::UpdateSemanticsCallback CreateEmbedderSemanticsUpdateCallbackV2(FlutterUpdateSemanticsCallback update_semantics_callback, void *user_data)
Definition embedder.cc:1634
static std::variant< flutter::ViewportMetrics, std::string > MakeViewportMetricsFromWindowMetrics(const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:1357
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:1422
#define FLUTTER_API_SYMBOL(symbol)
Definition embedder.h:67
FlutterKeyEventDeviceType
Definition embedder.h:1078
@ kFlutterKeyEventDeviceTypeKeyboard
Definition embedder.h:1079
@ kFlutterKeyEventDeviceTypeDirectionalPad
Definition embedder.h:1080
@ kFlutterKeyEventDeviceTypeHdmi
Definition embedder.h:1083
@ kFlutterKeyEventDeviceTypeJoystick
Definition embedder.h:1082
@ kFlutterKeyEventDeviceTypeGamepad
Definition embedder.h:1081
void(* FlutterUpdateSemanticsCustomActionCallback)(const FlutterSemanticsCustomAction *, void *)
Definition embedder.h:1520
void(* FlutterUpdateSemanticsCallback)(const FlutterSemanticsUpdate *, void *)
Definition embedder.h:1524
@ kFlutterEngineAOTDataSourceTypeElfPath
Definition embedder.h:2108
struct _FlutterPlatformMessageResponseHandle FlutterPlatformMessageResponseHandle
Definition embedder.h:1157
@ 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:1179
FlutterPointerPhase
The phase of the pointer event.
Definition embedder.h:963
@ kPanZoomUpdate
The pan/zoom updated.
Definition embedder.h:999
@ kHover
The pointer moved while up.
Definition embedder.h:995
@ kUp
Definition embedder.h:971
@ kPanZoomStart
A pan/zoom started on this pointer.
Definition embedder.h:997
@ kRemove
Definition embedder.h:993
@ kCancel
Definition embedder.h:964
@ kDown
Definition embedder.h:978
@ kAdd
Definition embedder.h:988
@ kMove
Definition embedder.h:983
@ kPanZoomEnd
The pan/zoom ended.
Definition embedder.h:1001
FlutterAccessibilityFeature
Definition embedder.h:91
void(* FlutterNativeThreadCallback)(FlutterNativeThreadType type, void *user_data)
Definition embedder.h:2103
@ kFlutterEngineDartObjectTypeString
Definition embedder.h:2016
@ kFlutterEngineDartObjectTypeBool
Definition embedder.h:2012
@ kFlutterEngineDartObjectTypeDouble
Definition embedder.h:2015
@ kFlutterEngineDartObjectTypeInt32
Definition embedder.h:2013
@ kFlutterEngineDartObjectTypeBuffer
Definition embedder.h:2019
@ kFlutterEngineDartObjectTypeInt64
Definition embedder.h:2014
@ kFlutterEngineDartObjectTypeNull
Definition embedder.h:2011
void(* FlutterLogMessageCallback)(const char *, const char *, void *)
Definition embedder.h:2128
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:2084
FlutterPointerSignalKind
The type of a pointer signal.
Definition embedder.h:1025
@ kFlutterPointerSignalKindScale
Definition embedder.h:1029
@ kFlutterPointerSignalKindScrollInertiaCancel
Definition embedder.h:1028
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1027
@ kFlutterPointerSignalKindNone
Definition embedder.h:1026
void(* FlutterUpdateSemanticsNodeCallback)(const FlutterSemanticsNode *, void *)
Definition embedder.h:1516
FlutterEngineDisplaysUpdateType
Definition embedder.h:1998
@ kFlutterEngineDisplaysUpdateTypeStartup
Definition embedder.h:2004
FlutterThreadPriority
Valid values for priority of Thread.
Definition embedder.h:256
@ kBackground
Suitable for threads that shouldn't disrupt high priority work.
Definition embedder.h:258
@ kDisplay
Suitable for threads which generate data for the display.
Definition embedder.h:262
@ kNormal
Default priority level.
Definition embedder.h:260
@ kRaster
Suitable for thread which raster data.
Definition embedder.h:264
FlutterSemanticsAction
Definition embedder.h:113
void(* FlutterKeyEventCallback)(bool, void *)
Definition embedder.h:1153
int64_t FlutterViewId
Definition embedder.h:273
FlutterKeyEventType
Definition embedder.h:1072
@ kFlutterKeyEventTypeDown
Definition embedder.h:1074
@ kFlutterKeyEventTypeUp
Definition embedder.h:1073
@ kFlutterKeyEventTypeRepeat
Definition embedder.h:1075
void(* FlutterUpdateSemanticsCallback2)(const FlutterSemanticsUpdate2 *, void *)
Definition embedder.h:1528
int64_t FlutterEngineDartPort
Definition embedder.h:2008
@ kFlutterOpenGLTargetTypeFramebuffer
Definition embedder.h:304
@ kFlutterOpenGLTargetTypeTexture
Definition embedder.h:301
@ kFlutterBackingStoreTypeSoftware2
Definition embedder.h:1749
@ kFlutterBackingStoreTypeMetal
Specifies a Metal backing store. This is backed by a Metal texture.
Definition embedder.h:1744
@ kFlutterBackingStoreTypeVulkan
Specifies a Vulkan backing store. This is backed by a Vulkan VkImage.
Definition embedder.h:1746
@ kFlutterBackingStoreTypeSoftware
Specified an software allocation for Flutter to render into using the CPU.
Definition embedder.h:1742
@ kFlutterBackingStoreTypeOpenGL
Definition embedder.h:1740
#define FLUTTER_ENGINE_VERSION
Definition embedder.h:70
FlutterPointerDeviceKind
The device type that created a pointer event.
Definition embedder.h:1005
@ kFlutterPointerDeviceKindTouch
Definition embedder.h:1007
@ kFlutterPointerDeviceKindTrackpad
Definition embedder.h:1009
@ kFlutterPointerDeviceKindStylus
Definition embedder.h:1008
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1006
#define SAFE_EXISTS(pointer, member)
Checks if the member exists and is non-null.
#define SAFE_ACCESS(pointer, member, default_value)
#define SAFE_EXISTS_ONE_OF(pointer, member1, member2)
Checks if exactly one of member1 or member2 exists and is non-null.
VkPhysicalDevice physical_device
Definition main.cc:51
VkDevice device
Definition main.cc:53
VkInstance instance
Definition main.cc:48
FlutterEngine engine
Definition main.cc:68
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
SkBitmap source
Definition examples.cpp:28
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
uint32_t uint32_t * format
#define FML_LOG(severity)
Definition logging.h:82
#define FML_DCHECK(condition)
Definition logging.h:103
const char * name
Definition fuchsia.cc:50
static const char * kApplicationKernelSnapshotFileName
Win32Message message
FlTexture * texture
double y
double x
SK_API GrBackendRenderTarget MakeGL(int width, int height, int sampleCnt, int stencilBits, const GrGLFramebufferInfo &glInfo)
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
SK_API GrBackendTexture MakeMtl(int width, int height, skgpu::Mipmapped, const GrMtlTextureInfo &mtlInfo, std::string_view label={})
SK_API GrBackendTexture MakeVk(int width, int height, const GrVkImageInfo &, std::string_view label={})
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
SK_API sk_sp< SkSurface > WrapPixels(const SkImageInfo &imageInfo, void *pixels, size_t rowBytes, const SkSurfaceProps *surfaceProps=nullptr)
SK_API sk_sp< SkSurface > WrapBackendRenderTarget(GrRecordingContext *context, const GrBackendRenderTarget &backendRenderTarget, GrSurfaceOrigin origin, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, RenderTargetReleaseProc releaseProc=nullptr, ReleaseContext releaseContext=nullptr)
void(*)(ReleaseContext) RenderTargetReleaseProc
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
void(*)(ReleaseContext) TextureReleaseProc
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
Settings SettingsFromCommandLine(const fml::CommandLine &command_line)
Definition switches.cc:228
@ 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 switches.h:57
@ kPointerButtonTouchContact
KeyEventType
Definition key_data.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 switches.h:41
KeyEventDeviceType
Definition key_data.h:34
it will be possible to load the file into Perfetto s trace viewer 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
Definition switches.h:259
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)
TSize< int64_t > ISize
Definition size.h:138
std::optional< SkColorInfo > getSkColorInfo(FlutterSoftwarePixelFormat pixfmt)
int32_t height
int32_t width
const Scalar scale
FlutterSize size
The size of the render target the engine expects to render into.
Definition embedder.h:1782
FlutterVulkanBackingStore vulkan
Definition embedder.h:1774
FlutterMetalBackingStore metal
Definition embedder.h:1772
FlutterBackingStoreType type
Specifies the type of backing store.
Definition embedder.h:1760
FlutterOpenGLBackingStore open_gl
The description of the OpenGL backing store.
Definition embedder.h:1766
FlutterSoftwareBackingStore software
The description of the software backing store.
Definition embedder.h:1768
FlutterSoftwareBackingStore2 software2
The description of the software backing store.
Definition embedder.h:1770
size_t struct_size
The size of this struct. Must be sizeof(FlutterBackingStore).
Definition embedder.h:1754
An update to whether a message channel has a listener set or not.
Definition embedder.h:1533
FlutterBackingStoreCreateCallback create_backing_store_callback
Definition embedder.h:1901
FlutterBackingStoreCollectCallback collect_backing_store_callback
Definition embedder.h:1906
A structure to represent a damage region.
Definition embedder.h:458
size_t num_rects
The number of rectangles within the damage region.
Definition embedder.h:462
size_t struct_size
The size of this struct. Must be sizeof(FlutterDamage).
Definition embedder.h:460
FlutterRect * damage
The actual damage region(s) in question.
Definition embedder.h:464
FlutterEngineDartObjectType type
Definition embedder.h:2067
const char * string_value
Definition embedder.h:2076
const FlutterEngineDartBuffer * buffer_value
Definition embedder.h:2077
Function-pointer-based versions of the APIs above.
Definition embedder.h:3317
size_t struct_size
The size of this struct. Must be sizeof(FlutterFrameInfo).
Definition embedder.h:475
FlutterUIntSize size
The size of the surface that will be backed by the fbo.
Definition embedder.h:477
FlutterSize size
The size of the layer (in physical pixels).
Definition embedder.h:1835
FlutterMetalTexture texture
Definition embedder.h:1663
FlutterMetalTextureFrameCallback external_texture_frame_callback
Definition embedder.h:702
FlutterMetalCommandQueueHandle present_command_queue
Alias for id<MTLCommandQueue>.
Definition embedder.h:687
FlutterMetalDeviceHandle device
Alias for id<MTLDevice>.
Definition embedder.h:685
FlutterMetalPresentCallback present_drawable_callback
Definition embedder.h:697
FlutterMetalTextureCallback get_next_drawable_callback
Definition embedder.h:692
FlutterMetalTextureHandle texture
Definition embedder.h:659
size_t struct_size
The size of this struct. Must be sizeof(FlutterMetalTexture).
Definition embedder.h:649
VoidCallback destruction_callback
Definition embedder.h:666
FlutterOpenGLTexture texture
A texture for Flutter to render into.
Definition embedder.h:1611
FlutterOpenGLTargetType type
Definition embedder.h:1608
FlutterOpenGLFramebuffer framebuffer
Definition embedder.h:1614
uint32_t name
The name of the framebuffer.
Definition embedder.h:394
VoidCallback destruction_callback
Definition embedder.h:401
void * user_data
User data to be returned on the invocation of the destruction callback.
Definition embedder.h:397
ProcResolver gl_proc_resolver
Definition embedder.h:552
BoolPresentInfoCallback present_with_info
Definition embedder.h:576
TextureFrameCallback gl_external_texture_frame_callback
Definition embedder.h:557
FlutterFrameBufferWithDamageCallback populate_existing_damage
Definition embedder.h:590
TransformationCallback surface_transformation
Definition embedder.h:551
BoolCallback make_resource_current
Definition embedder.h:535
UIntFrameInfoCallback fbo_with_frame_info_callback
Definition embedder.h:565
const char * channel
Definition embedder.h:1163
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition embedder.h:1034
size_t struct_size
The size of this struct. Must be sizeof(FlutterPresentInfo).
Definition embedder.h:497
A structure to represent a rectangle.
Definition embedder.h:435
double bottom
Definition embedder.h:439
double top
Definition embedder.h:437
double left
Definition embedder.h:436
double right
Definition embedder.h:438
FlutterVulkanRendererConfig vulkan
Definition embedder.h:830
FlutterMetalRendererConfig metal
Definition embedder.h:829
FlutterSoftwareRendererConfig software
Definition embedder.h:828
FlutterOpenGLRendererConfig open_gl
Definition embedder.h:827
FlutterRendererType type
Definition embedder.h:825
FlutterSemanticsNode * nodes
Definition embedder.h:1494
size_t nodes_count
The number of semantics node updates.
Definition embedder.h:1492
size_t custom_actions_count
The number of semantics custom action updates.
Definition embedder.h:1496
FlutterSemanticsCustomAction * custom_actions
Array of semantics custom actions. Has length custom_actions_count.
Definition embedder.h:1498
double height
Definition embedder.h:423
double width
Definition embedder.h:422
VoidCallback destruction_callback
Definition embedder.h:1650
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1641
FlutterSoftwarePixelFormat pixel_format
Definition embedder.h:1653
VoidCallback destruction_callback
Definition embedder.h:1632
size_t row_bytes
The number of bytes in a single row of the allocation.
Definition embedder.h:1623
SoftwareSurfacePresentCallback surface_present_callback
Definition embedder.h:821
double transY
vertical translation
Definition embedder.h:287
double pers2
perspective scale factor
Definition embedder.h:293
double skewX
horizontal skew factor
Definition embedder.h:279
double pers0
input x-axis perspective factor
Definition embedder.h:289
double scaleX
horizontal scale factor
Definition embedder.h:277
double skewY
vertical skew factor
Definition embedder.h:283
double scaleY
vertical scale factor
Definition embedder.h:285
double pers1
input y-axis perspective factor
Definition embedder.h:291
double transX
horizontal translation
Definition embedder.h:281
uint32_t width
Definition embedder.h:430
size_t struct_size
The size of this struct. Must be sizeof(FlutterVulkanImage).
Definition embedder.h:722
FlutterVulkanQueueHandle queue
Definition embedder.h:771
FlutterVulkanDeviceHandle device
Definition embedder.h:762
FlutterVulkanInstanceProcAddressCallback get_instance_proc_address_callback
Definition embedder.h:800
size_t enabled_instance_extension_count
Definition embedder.h:774
uint32_t queue_family_index
The queue family index of the VkQueue supplied in the next field.
Definition embedder.h:764
FlutterVulkanImageCallback get_next_image_callback
Definition embedder.h:804
const char ** enabled_instance_extensions
Definition embedder.h:781
const char ** enabled_device_extensions
Definition embedder.h:792
FlutterVulkanInstanceHandle instance
Definition embedder.h:757
FlutterVulkanPresentCallback present_image_callback
Definition embedder.h:810
FlutterVulkanPhysicalDeviceHandle physical_device
VkPhysicalDevice handle.
Definition embedder.h:759
GrGLenum fFormat
Definition GrGLTypes.h:183
GrGLenum fTarget
Definition GrGLTypes.h:181
VkImage fImage
Definition GrVkTypes.h:26
void operator()(Dart_LoadedElf *elf)
Definition embedder.cc:1405
static constexpr SkIRect MakeEmpty()
Definition SkRect.h:45
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkScalar fBottom
larger y-axis bounds
Definition extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition extension.cpp:15
Dart_HandleFinalizer callback
union _Dart_CObject::@86 value
Dart_CObject_Type type
struct _Dart_CObject::@86::@90 as_typed_data
const char * as_string
struct _Dart_CObject::@86::@91 as_external_typed_data
struct _Dart_CObject ** values
UniqueLoadedElf loaded_elf
Definition embedder.cc:1415
const uint8_t * vm_isolate_instrs
Definition embedder.cc:1419
const uint8_t * vm_snapshot_instrs
Definition embedder.cc:1417
const uint8_t * vm_snapshot_data
Definition embedder.cc:1416
const uint8_t * vm_isolate_data
Definition embedder.cc:1418
std::unique_ptr< flutter::PlatformMessage > message
Definition embedder.cc:1401
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
The ThreadConfig is the thread info include thread name, thread priority.
Definition thread.h:35
std::shared_ptr< Texture > resolve_texture
Definition formats.h:640
LoadAction load_action
Definition formats.h:641
std::shared_ptr< Texture > texture
Definition formats.h:639
StoreAction store_action
Definition formats.h:642
static constexpr Color DarkSlateGray()
Definition color.h:410
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
const uintptr_t id
DART_EXPORT Dart_LoadedElf * Dart_LoadELF(const char *filename, uint64_t file_offset, const char **error, const uint8_t **vm_snapshot_data, const uint8_t **vm_snapshot_instrs, const uint8_t **vm_isolate_data, const uint8_t **vm_isolate_instrs)
Please see documentation for Dart_LoadElf_Fd.
#define ERROR(message)
DART_EXPORT void Dart_UnloadELF(Dart_LoadedElf *loaded)
#define TRACE_EVENT0(category_group, name)
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_IMAGE_TILING_OPTIMAL
@ VK_IMAGE_USAGE_TRANSFER_DST_BIT
@ VK_IMAGE_USAGE_SAMPLED_BIT
@ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
@ VK_IMAGE_USAGE_TRANSFER_SRC_BIT
VkFormat
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
#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; \
}
#define STRUCT_HAS_MEMBER(pointer, member)
Dart_NativeFunction function
Definition fuchsia.cc:51

Typedef Documentation

◆ UniqueLoadedElf

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

Definition at line 1412 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.

Deprecated:
This API will be deprecated and is not part of the stable API. Please use the custom task runners API by setting an appropriate FlutterProjectArgs::custom_task_runners interface. This will yield better performance and the interface is stable.
Returns
The result of the call.

Definition at line 2758 of file embedder.cc.

2758 {
2760 return kSuccess;
2761}

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

1168 {
1169 FlutterBackingStore backing_store = {};
1170 backing_store.struct_size = sizeof(backing_store);
1171
1172 // Safe access checks on the compositor struct have been performed in
1173 // InferExternalViewEmbedderFromArgs and are not necessary here.
1174 auto c_create_callback = compositor->create_backing_store_callback;
1175 auto c_collect_callback = compositor->collect_backing_store_callback;
1176
1177 {
1178 TRACE_EVENT0("flutter", "FlutterCompositorCreateBackingStore");
1179 if (!c_create_callback(&config, &backing_store, compositor->user_data)) {
1180 FML_LOG(ERROR) << "Could not create the embedder backing store.";
1181 return nullptr;
1182 }
1183 }
1184
1185 if (backing_store.struct_size != sizeof(backing_store)) {
1186 FML_LOG(ERROR) << "Embedder modified the backing store struct size.";
1187 return nullptr;
1188 }
1189
1190 // In case we return early without creating an embedder render target, the
1191 // embedder has still given us ownership of its baton which we must return
1192 // back to it. If this method is successful, the closure is released when the
1193 // render target is eventually released.
1194 fml::ScopedCleanupClosure collect_callback(
1195 [c_collect_callback, backing_store, user_data = compositor->user_data]() {
1196 TRACE_EVENT0("flutter", "FlutterCompositorCollectBackingStore");
1197 c_collect_callback(&backing_store, user_data);
1198 });
1199
1200 // No safe access checks on the renderer are necessary since we allocated
1201 // the struct.
1202
1203 std::unique_ptr<flutter::EmbedderRenderTarget> render_target;
1204
1205 switch (backing_store.type) {
1207 switch (backing_store.open_gl.type) {
1209 auto skia_surface = MakeSkSurfaceFromBackingStore(
1210 context, config, &backing_store.open_gl.texture);
1211 render_target = MakeRenderTargetFromSkSurface(
1212 backing_store, std::move(skia_surface),
1213 collect_callback.Release());
1214 break;
1215 }
1217 if (enable_impeller) {
1219 backing_store, collect_callback.Release(), aiks_context, config,
1220 &backing_store.open_gl.framebuffer);
1221 break;
1222 } else {
1223 auto skia_surface = MakeSkSurfaceFromBackingStore(
1224 context, config, &backing_store.open_gl.framebuffer);
1225 render_target = MakeRenderTargetFromSkSurface(
1226 backing_store, std::move(skia_surface),
1227 collect_callback.Release());
1228 break;
1229 }
1230 }
1231 }
1232 break;
1233 }
1235 auto skia_surface = MakeSkSurfaceFromBackingStore(
1236 context, config, &backing_store.software);
1237 render_target = MakeRenderTargetFromSkSurface(
1238 backing_store, std::move(skia_surface), collect_callback.Release());
1239 break;
1240 }
1242 auto skia_surface = MakeSkSurfaceFromBackingStore(
1243 context, config, &backing_store.software2);
1244 render_target = MakeRenderTargetFromSkSurface(
1245 backing_store, std::move(skia_surface), collect_callback.Release());
1246 break;
1247 }
1249 if (enable_impeller) {
1251 backing_store, collect_callback.Release(), aiks_context, config,
1252 &backing_store.metal);
1253 } else {
1254 auto skia_surface = MakeSkSurfaceFromBackingStore(context, config,
1255 &backing_store.metal);
1256 render_target = MakeRenderTargetFromSkSurface(
1257 backing_store, std::move(skia_surface), collect_callback.Release());
1258 }
1259 break;
1260 }
1262 auto skia_surface =
1263 MakeSkSurfaceFromBackingStore(context, config, &backing_store.vulkan);
1264 render_target = MakeRenderTargetFromSkSurface(
1265 backing_store, std::move(skia_surface), collect_callback.Release());
1266 break;
1267 }
1268 };
1269
1270 if (!render_target) {
1271 FML_LOG(ERROR) << "Could not create a surface from an embedder provided "
1272 "render target.";
1273 }
1274 return render_target;
1275}

◆ CreateEmbedderSemanticsUpdateCallback()

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

Definition at line 1665 of file embedder.cc.

1666 {
1667 // There are three variants for the embedder API's semantic update callbacks.
1668 // Create a callback that maps to the embedder's desired semantic update API.
1669 //
1670 // Handle the case where the embedder registered the callback
1671 // 'updated_semantics_callback2'
1672 if (SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr) {
1674 args->update_semantics_callback2, user_data);
1675 }
1676
1677 // Handle the case where the embedder registered the deprecated callback
1678 // 'update_semantics_callback'.
1679 if (SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr) {
1681 args->update_semantics_callback, user_data);
1682 }
1683
1684 // Handle the case where the embedder registered the deprecated callbacks
1685 // 'update_semantics_node_callback' and
1686 // 'update_semantics_custom_action_callback'.
1687 FlutterUpdateSemanticsNodeCallback update_semantics_node_callback = nullptr;
1688 if (SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr) {
1689 update_semantics_node_callback = args->update_semantics_node_callback;
1690 }
1691
1693 update_semantics_custom_action_callback = nullptr;
1694 if (SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
1695 nullptr) {
1696 update_semantics_custom_action_callback =
1697 args->update_semantics_custom_action_callback;
1698 }
1699
1700 if (update_semantics_node_callback != nullptr ||
1701 update_semantics_custom_action_callback != nullptr) {
1703 update_semantics_node_callback, update_semantics_custom_action_callback,
1704 user_data);
1705 }
1706
1707 // Handle the case where the embedder registered no callbacks.
1708 return nullptr;
1709}

◆ CreateEmbedderSemanticsUpdateCallbackV1()

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

Definition at line 1585 of file embedder.cc.

1589 {
1590 return [update_semantics_node_callback,
1591 update_semantics_custom_action_callback,
1595 FlutterSemanticsUpdate* update_ptr = update.get();
1596
1597 // First, queue all node and custom action updates.
1598 if (update_semantics_node_callback != nullptr) {
1599 for (size_t i = 0; i < update_ptr->nodes_count; i++) {
1600 update_semantics_node_callback(&update_ptr->nodes[i], user_data);
1601 }
1602 }
1603
1604 if (update_semantics_custom_action_callback != nullptr) {
1605 for (size_t i = 0; i < update_ptr->custom_actions_count; i++) {
1606 update_semantics_custom_action_callback(&update_ptr->custom_actions[i],
1607 user_data);
1608 }
1609 }
1610
1611 // Second, mark node and action batches completed now that all
1612 // updates are queued.
1613 if (update_semantics_node_callback != nullptr) {
1614 const FlutterSemanticsNode batch_end_sentinel = {
1615 sizeof(FlutterSemanticsNode),
1617 };
1618 update_semantics_node_callback(&batch_end_sentinel, user_data);
1619 }
1620
1621 if (update_semantics_custom_action_callback != nullptr) {
1622 const FlutterSemanticsCustomAction batch_end_sentinel = {
1625 };
1626 update_semantics_custom_action_callback(&batch_end_sentinel, user_data);
1627 }
1628 };
1629}

◆ CreateEmbedderSemanticsUpdateCallbackV2()

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

Definition at line 1634 of file embedder.cc.

1636 {
1637 return [update_semantics_callback, user_data](
1638 const flutter::SemanticsNodeUpdates& nodes,
1641
1642 update_semantics_callback(update.get(), user_data);
1643 };
1644}

◆ CreateEmbedderSemanticsUpdateCallbackV3()

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

Definition at line 1649 of file embedder.cc.

1651 {
1652 return [update_semantics_callback, user_data](
1653 const flutter::SemanticsNodeUpdates& nodes,
1656
1657 update_semantics_callback(update.get(), user_data);
1658 };
1659}

◆ DispatchJSONPlatformMessage()

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

Definition at line 2966 of file embedder.cc.

2969 {
2970 if (channel_name.empty()) {
2971 return false;
2972 }
2973
2974 rapidjson::StringBuffer buffer;
2975 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
2976
2977 if (!document.Accept(writer)) {
2978 return false;
2979 }
2980
2981 const char* message = buffer.GetString();
2982
2983 if (message == nullptr || buffer.GetSize() == 0) {
2984 return false;
2985 }
2986
2987 auto platform_message = std::make_unique<flutter::PlatformMessage>(
2988 channel_name.c_str(), // channel
2990 buffer.GetSize()), // message
2991 nullptr // response
2992 );
2993
2994 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2995 ->SendPlatformMessage(std::move(platform_message));
2996}

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

2189 {
2190 if (!engine) {
2191 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2192 }
2193 if (!info || !info->view_metrics || !info->add_view_callback) {
2195 "Add view info handle was invalid.");
2196 }
2197
2198 FlutterViewId view_id = info->view_id;
2199 if (view_id == kFlutterImplicitViewId) {
2200 return LOG_EMBEDDER_ERROR(
2202 "Add view info was invalid. The implicit view cannot be added.");
2203 }
2204 if (SAFE_ACCESS(info->view_metrics, view_id, kFlutterImplicitViewId) !=
2205 view_id) {
2206 if (view_id == kFlutterImplicitViewId) {
2208 "Add view info was invalid. The info and "
2209 "window metric view IDs must match.");
2210 }
2211 }
2212
2213 // TODO(loicsharma): Return an error if the engine was initialized with
2214 // callbacks that are incompatible with multiple views.
2215 // https://github.com/flutter/flutter/issues/144806
2216
2217 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2219
2220 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2221 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2222 }
2223
2224 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2225
2226 // The engine must be running to add a view.
2227 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2228 if (!embedder_engine->IsValid()) {
2229 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2230 }
2231
2233 [c_callback = info->add_view_callback,
2234 user_data = info->user_data](bool added) {
2237 result.added = added;
2238 result.user_data = user_data;
2239 c_callback(&result);
2240 };
2241
2242 embedder_engine->GetShell().GetPlatformView()->AddView(view_id, metrics,
2243 callback);
2244 return kSuccess;
2245}

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

1476 {
1477 if (!data) {
1478 // Deleting a null object should be a no-op.
1479 return kSuccess;
1480 }
1481
1482 // Created in a unique pointer in `FlutterEngineCreateAOTData`.
1483 delete data;
1484 return kSuccess;
1485}

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

1424 {
1427 "AOT data can only be created in AOT mode.");
1428 } else if (!source) {
1429 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null source specified.");
1430 } else if (!data_out) {
1431 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null data_out specified.");
1432 }
1433
1434 switch (source->type) {
1436 if (!source->elf_path || !fml::IsFile(source->elf_path)) {
1438 "Invalid ELF path specified.");
1439 }
1440
1441 auto aot_data = std::make_unique<_FlutterEngineAOTData>();
1442 const char* error = nullptr;
1443
1444#if OS_FUCHSIA
1445 // TODO(gw280): https://github.com/flutter/flutter/issues/50285
1446 // Dart doesn't implement Dart_LoadELF on Fuchsia
1447 Dart_LoadedElf* loaded_elf = nullptr;
1448#else
1449 Dart_LoadedElf* loaded_elf = Dart_LoadELF(
1450 source->elf_path, // file path
1451 0, // file offset
1452 &error, // error (out)
1453 &aot_data->vm_snapshot_data, // vm snapshot data (out)
1454 &aot_data->vm_snapshot_instrs, // vm snapshot instr (out)
1455 &aot_data->vm_isolate_data, // vm isolate data (out)
1456 &aot_data->vm_isolate_instrs // vm isolate instr (out)
1457 );
1458#endif
1459
1460 if (loaded_elf == nullptr) {
1462 }
1463
1464 aot_data->loaded_elf.reset(loaded_elf);
1465
1466 *data_out = aot_data.release();
1467 return kSuccess;
1468 }
1469 }
1470
1471 return LOG_EMBEDDER_ERROR(
1473 "Invalid FlutterEngineAOTDataSourceType type specified.");
1474}

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

2292 {
2293 if (engine == nullptr) {
2294 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2295 }
2296
2297 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2298 embedder_engine->NotifyDestroyed();
2299 embedder_engine->CollectShell();
2300 return kSuccess;
2301}

◆ 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.

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

2854 {
2855 if (engine == nullptr) {
2856 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2857 }
2858 auto engine_action = static_cast<flutter::SemanticsAction>(action);
2859 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2861 node_id, engine_action,
2862 fml::MallocMapping::Copy(data, data_length))) {
2864 "Could not dispatch semantics action.");
2865 }
2866 return kSuccess;
2867}

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

2949 {
2951}

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

3330 {
3331 if (!table) {
3332 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null table specified.");
3333 }
3334#define SET_PROC(member, function) \
3335 if (STRUCT_HAS_MEMBER(table, member)) { \
3336 table->member = &function; \
3337 }
3338
3339 SET_PROC(CreateAOTData, FlutterEngineCreateAOTData);
3340 SET_PROC(CollectAOTData, FlutterEngineCollectAOTData);
3343 SET_PROC(Initialize, FlutterEngineInitialize);
3344 SET_PROC(Deinitialize, FlutterEngineDeinitialize);
3345 SET_PROC(RunInitialized, FlutterEngineRunInitialized);
3346 SET_PROC(SendWindowMetricsEvent, FlutterEngineSendWindowMetricsEvent);
3347 SET_PROC(SendPointerEvent, FlutterEngineSendPointerEvent);
3348 SET_PROC(SendKeyEvent, FlutterEngineSendKeyEvent);
3349 SET_PROC(SendPlatformMessage, FlutterEngineSendPlatformMessage);
3350 SET_PROC(PlatformMessageCreateResponseHandle,
3352 SET_PROC(PlatformMessageReleaseResponseHandle,
3354 SET_PROC(SendPlatformMessageResponse,
3356 SET_PROC(RegisterExternalTexture, FlutterEngineRegisterExternalTexture);
3357 SET_PROC(UnregisterExternalTexture, FlutterEngineUnregisterExternalTexture);
3358 SET_PROC(MarkExternalTextureFrameAvailable,
3360 SET_PROC(UpdateSemanticsEnabled, FlutterEngineUpdateSemanticsEnabled);
3361 SET_PROC(UpdateAccessibilityFeatures,
3363 SET_PROC(DispatchSemanticsAction, FlutterEngineDispatchSemanticsAction);
3365 SET_PROC(ReloadSystemFonts, FlutterEngineReloadSystemFonts);
3366 SET_PROC(TraceEventDurationBegin, FlutterEngineTraceEventDurationBegin);
3367 SET_PROC(TraceEventDurationEnd, FlutterEngineTraceEventDurationEnd);
3368 SET_PROC(TraceEventInstant, FlutterEngineTraceEventInstant);
3369 SET_PROC(PostRenderThreadTask, FlutterEnginePostRenderThreadTask);
3372 SET_PROC(UpdateLocales, FlutterEngineUpdateLocales);
3373 SET_PROC(RunsAOTCompiledDartCode, FlutterEngineRunsAOTCompiledDartCode);
3374 SET_PROC(PostDartObject, FlutterEnginePostDartObject);
3375 SET_PROC(NotifyLowMemoryWarning, FlutterEngineNotifyLowMemoryWarning);
3376 SET_PROC(PostCallbackOnAllNativeThreads,
3378 SET_PROC(NotifyDisplayUpdate, FlutterEngineNotifyDisplayUpdate);
3379 SET_PROC(ScheduleFrame, FlutterEngineScheduleFrame);
3380 SET_PROC(SetNextFrameCallback, FlutterEngineSetNextFrameCallback);
3382 SET_PROC(RemoveView, FlutterEngineRemoveView);
3383#undef SET_PROC
3384
3385 return kSuccess;
3386}

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

1732 {
1733 // Step 0: Figure out arguments for shell creation.
1734 if (version != FLUTTER_ENGINE_VERSION) {
1735 return LOG_EMBEDDER_ERROR(
1737 "Flutter embedder version mismatch. There has been a breaking change. "
1738 "Please consult the changelog and update the embedder.");
1739 }
1740
1741 if (engine_out == nullptr) {
1743 "The engine out parameter was missing.");
1744 }
1745
1746 if (args == nullptr) {
1748 "The Flutter project arguments were missing.");
1749 }
1750
1751 if (SAFE_ACCESS(args, assets_path, nullptr) == nullptr) {
1752 return LOG_EMBEDDER_ERROR(
1754 "The assets path in the Flutter project arguments was missing.");
1755 }
1756
1757 if (SAFE_ACCESS(args, main_path__unused__, nullptr) != nullptr) {
1758 FML_LOG(WARNING)
1759 << "FlutterProjectArgs.main_path is deprecated and should be set null.";
1760 }
1761
1762 if (SAFE_ACCESS(args, packages_path__unused__, nullptr) != nullptr) {
1763 FML_LOG(WARNING) << "FlutterProjectArgs.packages_path is deprecated and "
1764 "should be set null.";
1765 }
1766
1767 if (!IsRendererValid(config)) {
1769 "The renderer configuration was invalid.");
1770 }
1771
1772 std::string icu_data_path;
1773 if (SAFE_ACCESS(args, icu_data_path, nullptr) != nullptr) {
1774 icu_data_path = SAFE_ACCESS(args, icu_data_path, nullptr);
1775 }
1776
1777 if (SAFE_ACCESS(args, persistent_cache_path, nullptr) != nullptr) {
1778 std::string persistent_cache_path =
1779 SAFE_ACCESS(args, persistent_cache_path, nullptr);
1781 }
1782
1783 if (SAFE_ACCESS(args, is_persistent_cache_read_only, false)) {
1785 }
1786
1787 fml::CommandLine command_line;
1788 if (SAFE_ACCESS(args, command_line_argc, 0) != 0 &&
1789 SAFE_ACCESS(args, command_line_argv, nullptr) != nullptr) {
1790 command_line = fml::CommandLineFromArgcArgv(
1791 SAFE_ACCESS(args, command_line_argc, 0),
1792 SAFE_ACCESS(args, command_line_argv, nullptr));
1793 }
1794
1796
1797 if (SAFE_ACCESS(args, aot_data, nullptr)) {
1798 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) ||
1799 SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) ||
1800 SAFE_ACCESS(args, isolate_snapshot_data, nullptr) ||
1801 SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr)) {
1802 return LOG_EMBEDDER_ERROR(
1804 "Multiple AOT sources specified. Embedders should provide either "
1805 "*_snapshot_* buffers or aot_data, not both.");
1806 }
1807 }
1808
1811 } else {
1813 }
1814
1815 settings.icu_data_path = icu_data_path;
1816 settings.assets_path = args->assets_path;
1817 settings.leak_vm = !SAFE_ACCESS(args, shutdown_dart_vm_when_done, false);
1818 settings.old_gen_heap_size = SAFE_ACCESS(args, dart_old_gen_heap_size, -1);
1819
1821 // Verify the assets path contains Dart 2 kernel assets.
1822 const std::string kApplicationKernelSnapshotFileName = "kernel_blob.bin";
1823 std::string application_kernel_path = fml::paths::JoinPaths(
1825 if (!fml::IsFile(application_kernel_path)) {
1826 return LOG_EMBEDDER_ERROR(
1828 "Not running in AOT mode but could not resolve the kernel binary.");
1829 }
1830 settings.application_kernel_asset = kApplicationKernelSnapshotFileName;
1831 }
1832
1833 settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
1835 };
1836 settings.task_observer_remove = [](intptr_t key) {
1838 };
1839 if (SAFE_ACCESS(args, root_isolate_create_callback, nullptr) != nullptr) {
1841 SAFE_ACCESS(args, root_isolate_create_callback, nullptr);
1842 settings.root_isolate_create_callback =
1843 [callback, user_data](const auto& isolate) { callback(user_data); };
1844 }
1845 if (SAFE_ACCESS(args, log_message_callback, nullptr) != nullptr) {
1847 SAFE_ACCESS(args, log_message_callback, nullptr);
1848 settings.log_message_callback = [callback, user_data](
1849 const std::string& tag,
1850 const std::string& message) {
1851 callback(tag.c_str(), message.c_str(), user_data);
1852 };
1853 }
1854 if (SAFE_ACCESS(args, log_tag, nullptr) != nullptr) {
1855 settings.log_tag = SAFE_ACCESS(args, log_tag, nullptr);
1856 }
1857
1858 bool has_update_semantics_2_callback =
1859 SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr;
1860 bool has_update_semantics_callback =
1861 SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr;
1862 bool has_legacy_update_semantics_callback =
1863 SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr ||
1864 SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
1865 nullptr;
1866
1867 int semantic_callback_count = (has_update_semantics_2_callback ? 1 : 0) +
1868 (has_update_semantics_callback ? 1 : 0) +
1869 (has_legacy_update_semantics_callback ? 1 : 0);
1870
1871 if (semantic_callback_count > 1) {
1872 return LOG_EMBEDDER_ERROR(
1874 "Multiple semantics update callbacks provided. "
1875 "Embedders should provide either `update_semantics_callback2`, "
1876 "`update_semantics_callback`, or both "
1877 "`update_semantics_node_callback` and "
1878 "`update_semantics_custom_action_callback`.");
1879 }
1880
1882 update_semantics_callback =
1884
1886 platform_message_response_callback = nullptr;
1887 if (SAFE_ACCESS(args, platform_message_callback, nullptr) != nullptr) {
1888 platform_message_response_callback =
1889 [ptr = args->platform_message_callback,
1890 user_data](std::unique_ptr<flutter::PlatformMessage> message) {
1891 auto handle = new FlutterPlatformMessageResponseHandle();
1892 const FlutterPlatformMessage incoming_message = {
1893 sizeof(FlutterPlatformMessage), // struct_size
1894 message->channel().c_str(), // channel
1895 message->data().GetMapping(), // message
1896 message->data().GetSize(), // message_size
1897 handle, // response_handle
1898 };
1899 handle->message = std::move(message);
1900 return ptr(&incoming_message, user_data);
1901 };
1902 }
1903
1904 flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr;
1905 if (SAFE_ACCESS(args, vsync_callback, nullptr) != nullptr) {
1906 vsync_callback = [ptr = args->vsync_callback, user_data](intptr_t baton) {
1907 return ptr(user_data, baton);
1908 };
1909 }
1910
1912 compute_platform_resolved_locale_callback = nullptr;
1913 if (SAFE_ACCESS(args, compute_platform_resolved_locale_callback, nullptr) !=
1914 nullptr) {
1915 compute_platform_resolved_locale_callback =
1916 [ptr = args->compute_platform_resolved_locale_callback](
1917 const std::vector<std::string>& supported_locales_data) {
1918 const size_t number_of_strings_per_locale = 3;
1919 size_t locale_count =
1920 supported_locales_data.size() / number_of_strings_per_locale;
1921 std::vector<FlutterLocale> supported_locales;
1922 std::vector<const FlutterLocale*> supported_locales_ptr;
1923 for (size_t i = 0; i < locale_count; ++i) {
1924 supported_locales.push_back(
1925 {.struct_size = sizeof(FlutterLocale),
1926 .language_code =
1927 supported_locales_data[i * number_of_strings_per_locale +
1928 0]
1929 .c_str(),
1930 .country_code =
1931 supported_locales_data[i * number_of_strings_per_locale +
1932 1]
1933 .c_str(),
1934 .script_code =
1935 supported_locales_data[i * number_of_strings_per_locale +
1936 2]
1937 .c_str(),
1938 .variant_code = nullptr});
1939 supported_locales_ptr.push_back(&supported_locales[i]);
1940 }
1941
1942 const FlutterLocale* result =
1943 ptr(supported_locales_ptr.data(), locale_count);
1944
1945 std::unique_ptr<std::vector<std::string>> out =
1946 std::make_unique<std::vector<std::string>>();
1947 if (result) {
1948 std::string language_code(SAFE_ACCESS(result, language_code, ""));
1949 if (language_code != "") {
1950 out->push_back(language_code);
1951 out->emplace_back(SAFE_ACCESS(result, country_code, ""));
1952 out->emplace_back(SAFE_ACCESS(result, script_code, ""));
1953 }
1954 }
1955 return out;
1956 };
1957 }
1958
1960 on_pre_engine_restart_callback = nullptr;
1961 if (SAFE_ACCESS(args, on_pre_engine_restart_callback, nullptr) != nullptr) {
1962 on_pre_engine_restart_callback = [ptr =
1963 args->on_pre_engine_restart_callback,
1964 user_data]() { return ptr(user_data); };
1965 }
1966
1968 nullptr;
1969 if (SAFE_ACCESS(args, channel_update_callback, nullptr) != nullptr) {
1970 channel_update_callback = [ptr = args->channel_update_callback, user_data](
1971 const std::string& name, bool listening) {
1973 listening};
1974 ptr(&update, user_data);
1975 };
1976 }
1977
1978 auto external_view_embedder_result = InferExternalViewEmbedderFromArgs(
1979 SAFE_ACCESS(args, compositor, nullptr), settings.enable_impeller);
1980 if (external_view_embedder_result.second) {
1982 "Compositor arguments were invalid.");
1983 }
1984
1986 {
1987 update_semantics_callback, //
1988 platform_message_response_callback, //
1989 vsync_callback, //
1990 compute_platform_resolved_locale_callback, //
1991 on_pre_engine_restart_callback, //
1992 channel_update_callback, //
1993 };
1994
1995 auto on_create_platform_view = InferPlatformViewCreationCallback(
1996 config, user_data, platform_dispatch_table,
1997 std::move(external_view_embedder_result.first), settings.enable_impeller);
1998
1999 if (!on_create_platform_view) {
2000 return LOG_EMBEDDER_ERROR(
2002 "Could not infer platform view creation callback.");
2003 }
2004
2006 [](flutter::Shell& shell) {
2007 return std::make_unique<flutter::Rasterizer>(shell);
2008 };
2009
2010 using ExternalTextureResolver = flutter::EmbedderExternalTextureResolver;
2011 std::unique_ptr<ExternalTextureResolver> external_texture_resolver;
2012 external_texture_resolver = std::make_unique<ExternalTextureResolver>();
2013
2014#ifdef SHELL_ENABLE_GL
2016 external_texture_callback;
2017 if (config->type == kOpenGL) {
2018 const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl;
2019 if (SAFE_ACCESS(open_gl_config, gl_external_texture_frame_callback,
2020 nullptr) != nullptr) {
2021 external_texture_callback =
2022 [ptr = open_gl_config->gl_external_texture_frame_callback, user_data](
2023 int64_t texture_identifier, size_t width,
2024 size_t height) -> std::unique_ptr<FlutterOpenGLTexture> {
2025 std::unique_ptr<FlutterOpenGLTexture> texture =
2026 std::make_unique<FlutterOpenGLTexture>();
2027 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2028 return nullptr;
2029 }
2030 return texture;
2031 };
2032 external_texture_resolver =
2033 std::make_unique<ExternalTextureResolver>(external_texture_callback);
2034 }
2035 }
2036#endif
2037#ifdef SHELL_ENABLE_METAL
2039 external_texture_metal_callback;
2040 if (config->type == kMetal) {
2041 const FlutterMetalRendererConfig* metal_config = &config->metal;
2042 if (SAFE_ACCESS(metal_config, external_texture_frame_callback, nullptr)) {
2043 external_texture_metal_callback =
2044 [ptr = metal_config->external_texture_frame_callback, user_data](
2045 int64_t texture_identifier, size_t width,
2046 size_t height) -> std::unique_ptr<FlutterMetalExternalTexture> {
2047 std::unique_ptr<FlutterMetalExternalTexture> texture =
2048 std::make_unique<FlutterMetalExternalTexture>();
2049 texture->struct_size = sizeof(FlutterMetalExternalTexture);
2050 if (!ptr(user_data, texture_identifier, width, height, texture.get())) {
2051 return nullptr;
2052 }
2053 return texture;
2054 };
2055 external_texture_resolver = std::make_unique<ExternalTextureResolver>(
2056 external_texture_metal_callback);
2057 }
2058 }
2059#endif
2060 auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
2061 auto thread_config_callback = [&custom_task_runners](
2062 const fml::Thread::ThreadConfig& config) {
2064 if (!custom_task_runners || !custom_task_runners->thread_priority_setter) {
2065 return;
2066 }
2068 switch (config.priority) {
2071 break;
2074 break;
2077 break;
2080 break;
2081 }
2082 custom_task_runners->thread_priority_setter(priority);
2083 };
2084 auto thread_host =
2086 custom_task_runners, thread_config_callback);
2087
2088 if (!thread_host || !thread_host->IsValid()) {
2090 "Could not set up or infer thread configuration "
2091 "to run the Flutter engine on.");
2092 }
2093
2094 auto task_runners = thread_host->GetTaskRunners();
2095
2096 if (!task_runners.IsValid()) {
2098 "Task runner configuration was invalid.");
2099 }
2100
2101 auto run_configuration =
2103
2104 if (SAFE_ACCESS(args, custom_dart_entrypoint, nullptr) != nullptr) {
2105 auto dart_entrypoint = std::string{args->custom_dart_entrypoint};
2106 if (!dart_entrypoint.empty()) {
2107 run_configuration.SetEntrypoint(std::move(dart_entrypoint));
2108 }
2109 }
2110
2111 if (SAFE_ACCESS(args, dart_entrypoint_argc, 0) > 0) {
2112 if (SAFE_ACCESS(args, dart_entrypoint_argv, nullptr) == nullptr) {
2114 "Could not determine Dart entrypoint arguments "
2115 "as dart_entrypoint_argc "
2116 "was set, but dart_entrypoint_argv was null.");
2117 }
2118 std::vector<std::string> arguments(args->dart_entrypoint_argc);
2119 for (int i = 0; i < args->dart_entrypoint_argc; ++i) {
2120 arguments[i] = std::string{args->dart_entrypoint_argv[i]};
2121 }
2122 run_configuration.SetEntrypointArgs(std::move(arguments));
2123 }
2124
2125 if (!run_configuration.IsValid()) {
2126 return LOG_EMBEDDER_ERROR(
2128 "Could not infer the Flutter project to run from given arguments.");
2129 }
2130
2131 // Create the engine but don't launch the shell or run the root isolate.
2132 auto embedder_engine = std::make_unique<flutter::EmbedderEngine>(
2133 std::move(thread_host), //
2134 std::move(task_runners), //
2135 std::move(settings), //
2136 std::move(run_configuration), //
2137 on_create_platform_view, //
2138 on_create_rasterizer, //
2139 std::move(external_texture_resolver) //
2140 );
2141
2142 // Release the ownership of the embedder engine to the caller.
2143 *engine_out = reinterpret_cast<FLUTTER_API_SYMBOL(FlutterEngine)>(
2144 embedder_engine.release());
2145 return kSuccess;
2146}

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

2805 {
2806 if (engine == nullptr) {
2807 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2808 }
2809 if (texture_identifier == 0) {
2810 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid texture identifier.");
2811 }
2812 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2813 ->MarkTextureFrameAvailable(texture_identifier)) {
2814 return LOG_EMBEDDER_ERROR(
2816 "Could not mark the texture frame as being available.");
2817 }
2818 return kSuccess;
2819}

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

3250 {
3251 if (raw_engine == nullptr) {
3252 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3253 }
3254
3255 if (!ValidDisplayConfiguration(embedder_displays, display_count)) {
3256 return LOG_EMBEDDER_ERROR(
3258 "Invalid FlutterEngineDisplay configuration specified.");
3259 }
3260
3261 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3262
3263 switch (update_type) {
3265 std::vector<std::unique_ptr<flutter::Display>> displays;
3266 const auto* display = embedder_displays;
3267 for (size_t i = 0; i < display_count; i++) {
3268 displays.push_back(std::make_unique<flutter::Display>(
3269 SAFE_ACCESS(display, display_id, i), //
3270 SAFE_ACCESS(display, refresh_rate, 0), //
3271 SAFE_ACCESS(display, width, 0), //
3272 SAFE_ACCESS(display, height, 0), //
3273 SAFE_ACCESS(display, device_pixel_ratio, 1)));
3274 display = reinterpret_cast<const FlutterEngineDisplay*>(
3275 reinterpret_cast<const uint8_t*>(display) + display->struct_size);
3276 }
3277 engine->GetShell().OnDisplayUpdates(std::move(displays));
3278 return kSuccess;
3279 }
3280 default:
3281 return LOG_EMBEDDER_ERROR(
3283 "Invalid FlutterEngineDisplaysUpdateType type specified.");
3284 }
3285}

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

3186 {
3187 auto engine = reinterpret_cast<flutter::EmbedderEngine*>(raw_engine);
3188 if (engine == nullptr || !engine->IsValid()) {
3189 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine was invalid.");
3190 }
3191
3192 engine->GetShell().NotifyLowMemoryWarning();
3193
3194 rapidjson::Document document;
3195 auto& allocator = document.GetAllocator();
3196
3197 document.SetObject();
3198 document.AddMember("type", "memoryPressure", allocator);
3199
3200 return DispatchJSONPlatformMessage(raw_engine, document, "flutter/system")
3201 ? kSuccess
3204 "Could not dispatch the low memory notification message.");
3205}

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

2873 {
2874 if (engine == nullptr) {
2875 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2876 }
2877
2878 TRACE_EVENT0("flutter", "FlutterEngineOnVsync");
2879
2880 auto start_time = fml::TimePoint::FromEpochDelta(
2881 fml::TimeDelta::FromNanoseconds(frame_start_time_nanos));
2882
2883 auto target_time = fml::TimePoint::FromEpochDelta(
2884 fml::TimeDelta::FromNanoseconds(frame_target_time_nanos));
2885
2886 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->OnVsyncEvent(
2887 baton, start_time, target_time)) {
2888 return LOG_EMBEDDER_ERROR(
2890 "Could not notify the running engine instance of a Vsync event.");
2891 }
2892
2893 return kSuccess;
2894}

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

3210 {
3211 if (engine == nullptr) {
3212 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3213 }
3214
3215 if (callback == nullptr) {
3217 "Invalid native thread callback.");
3218 }
3219
3220 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
3221 ->PostTaskOnEngineManagedNativeThreads(
3224 })
3225 ? kSuccess
3227 "Internal error while attempting to post "
3228 "tasks to all threads.");
3229}

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

3064 {
3065 if (engine == nullptr) {
3066 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3067 }
3068
3069 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->IsValid()) {
3070 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine not running.");
3071 }
3072
3073 if (port == ILLEGAL_PORT) {
3075 "Attempted to post to an illegal port.");
3076 }
3077
3078 if (object == nullptr) {
3080 "Invalid Dart object to post.");
3081 }
3082
3083 Dart_CObject dart_object = {};
3084 fml::ScopedCleanupClosure typed_data_finalizer;
3085
3086 switch (object->type) {
3088 dart_object.type = Dart_CObject_kNull;
3089 break;
3091 dart_object.type = Dart_CObject_kBool;
3092 dart_object.value.as_bool = object->bool_value;
3093 break;
3095 dart_object.type = Dart_CObject_kInt32;
3096 dart_object.value.as_int32 = object->int32_value;
3097 break;
3099 dart_object.type = Dart_CObject_kInt64;
3100 dart_object.value.as_int64 = object->int64_value;
3101 break;
3103 dart_object.type = Dart_CObject_kDouble;
3104 dart_object.value.as_double = object->double_value;
3105 break;
3107 if (object->string_value == nullptr) {
3109 "kFlutterEngineDartObjectTypeString must be "
3110 "a null terminated string but was null.");
3111 }
3112 dart_object.type = Dart_CObject_kString;
3113 dart_object.value.as_string = const_cast<char*>(object->string_value);
3114 break;
3116 auto* buffer = SAFE_ACCESS(object->buffer_value, buffer, nullptr);
3117 if (buffer == nullptr) {
3119 "kFlutterEngineDartObjectTypeBuffer must "
3120 "specify a buffer but found nullptr.");
3121 }
3122 auto buffer_size = SAFE_ACCESS(object->buffer_value, buffer_size, 0);
3123 auto callback =
3124 SAFE_ACCESS(object->buffer_value, buffer_collect_callback, nullptr);
3125 auto user_data = SAFE_ACCESS(object->buffer_value, user_data, nullptr);
3126
3127 // The user has provided a callback, let them manage the lifecycle of
3128 // the underlying data. If not, copy it out from the provided buffer.
3129
3130 if (callback == nullptr) {
3131 dart_object.type = Dart_CObject_kTypedData;
3133 dart_object.value.as_typed_data.length = buffer_size;
3134 dart_object.value.as_typed_data.values = buffer;
3135 } else {
3136 struct ExternalTypedDataPeer {
3137 void* user_data = nullptr;
3138 VoidCallback trampoline = nullptr;
3139 };
3140 auto peer = new ExternalTypedDataPeer();
3141 peer->user_data = user_data;
3142 peer->trampoline = callback;
3143 // This finalizer is set so that in case of failure of the
3144 // Dart_PostCObject below, we collect the peer. The embedder is still
3145 // responsible for collecting the buffer in case of non-kSuccess
3146 // returns from this method. This finalizer must be released in case
3147 // of kSuccess returns from this method.
3148 typed_data_finalizer.SetClosure([peer]() {
3149 // This is the tiny object we use as the peer to the Dart call so
3150 // that we can attach the a trampoline to the embedder supplied
3151 // callback. In case of error, we need to collect this object lest
3152 // we introduce a tiny leak.
3153 delete peer;
3154 });
3159 dart_object.value.as_external_typed_data.peer = peer;
3161 +[](void* unused_isolate_callback_data, void* peer) {
3162 auto typed_peer = reinterpret_cast<ExternalTypedDataPeer*>(peer);
3163 typed_peer->trampoline(typed_peer->user_data);
3164 delete typed_peer;
3165 };
3166 }
3167 } break;
3168 default:
3169 return LOG_EMBEDDER_ERROR(
3171 "Invalid FlutterEngineDartObjectType type specified.");
3172 }
3173
3174 if (!Dart_PostCObject(port, &dart_object)) {
3176 "Could not post the object to the Dart VM.");
3177 }
3178
3179 // On a successful call, the VM takes ownership of and is responsible for
3180 // invoking the finalizer.
3181 typed_data_finalizer.Release();
3182 return kSuccess;
3183}

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

2930 {
2931 if (engine == nullptr) {
2932 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2933 }
2934
2935 if (callback == nullptr) {
2937 "Render thread callback was null.");
2938 }
2939
2940 auto task = [callback, baton]() { callback(baton); };
2941
2942 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2943 ->PostRenderThreadTask(task)
2944 ? kSuccess
2946 "Could not post the render thread task.");
2947}

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

2765 {
2766 if (engine == nullptr) {
2767 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2768 }
2769
2770 if (texture_identifier == 0) {
2772 "Texture identifier was invalid.");
2773 }
2774 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->RegisterTexture(
2775 texture_identifier)) {
2777 "Could not register the specified texture.");
2778 }
2779 return kSuccess;
2780}

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

2897 {
2898 if (engine == nullptr) {
2899 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2900 }
2901
2902 TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
2903
2904 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2905 ->ReloadSystemFonts()) {
2907 "Could not reload system fonts.");
2908 }
2909
2910 return kSuccess;
2911}

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

2250 {
2251 if (!engine) {
2252 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2253 }
2254 if (!info || !info->remove_view_callback) {
2256 "Remove view info handle was invalid.");
2257 }
2258
2259 if (info->view_id == kFlutterImplicitViewId) {
2260 return LOG_EMBEDDER_ERROR(
2262 "Remove view info was invalid. The implicit view cannot be removed.");
2263 }
2264
2265 // TODO(loicsharma): Return an error if the engine was initialized with
2266 // callbacks that are incompatible with multiple views.
2267 // https://github.com/flutter/flutter/issues/144806
2268
2269 // The engine must be running to remove a view.
2270 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2271 if (!embedder_engine->IsValid()) {
2272 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2273 }
2274
2276 [c_callback = info->remove_view_callback,
2277 user_data = info->user_data](bool removed) {
2280 result.removed = removed;
2281 result.user_data = user_data;
2282 c_callback(&result);
2283 };
2284
2285 embedder_engine->GetShell().GetPlatformView()->RemoveView(info->view_id,
2286 callback);
2287 return kSuccess;
2288}

◆ 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 via the FlutterInitializeCall. 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 1711 of file embedder.cc.

1716 {
1717 auto result =
1718 FlutterEngineInitialize(version, config, args, user_data, engine_out);
1719
1720 if (result != kSuccess) {
1721 return result;
1722 }
1723
1724 return FlutterEngineRunInitialized(*engine_out);
1725}

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

2149 {
2150 if (!engine) {
2151 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2152 }
2153
2154 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2155
2156 // The engine must not already be running. Initialize may only be called
2157 // once on an engine instance.
2158 if (embedder_engine->IsValid()) {
2159 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2160 }
2161
2162 // Step 1: Launch the shell.
2163 if (!embedder_engine->LaunchShell()) {
2165 "Could not launch the engine using supplied "
2166 "initialization arguments.");
2167 }
2168
2169 // Step 2: Tell the platform view to initialize itself.
2170 if (!embedder_engine->NotifyCreated()) {
2172 "Could not create platform view components.");
2173 }
2174
2175 // Step 3: Launch the root isolate.
2176 if (!embedder_engine->RunRootIsolate()) {
2177 return LOG_EMBEDDER_ERROR(
2179 "Could not run the root isolate of the Flutter application using the "
2180 "project arguments specified.");
2181 }
2182
2183 return kSuccess;
2184}

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

3057 {
3059}

◆ 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 engine 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 2953 of file embedder.cc.

2955 {
2956 if (engine == nullptr) {
2957 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2958 }
2959
2960 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->RunTask(task)
2961 ? kSuccess
2963 "Could not run the specified task.");
2964}

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

3288 {
3289 if (engine == nullptr) {
3290 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3291 }
3292
3293 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->ScheduleFrame()
3294 ? kSuccess
3296 "Could not schedule frame.");
3297}

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

2579 {
2580 if (engine == nullptr) {
2581 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2582 }
2583
2584 if (event == nullptr) {
2585 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid key event.");
2586 }
2587
2588 const char* character = SAFE_ACCESS(event, character, nullptr);
2589
2590 flutter::KeyData key_data;
2591 key_data.Clear();
2592 key_data.timestamp = static_cast<uint64_t>(SAFE_ACCESS(event, timestamp, 0));
2593 key_data.type = MapKeyEventType(
2595 key_data.physical = SAFE_ACCESS(event, physical, 0);
2596 key_data.logical = SAFE_ACCESS(event, logical, 0);
2597 key_data.synthesized = SAFE_ACCESS(event, synthesized, false);
2599 event, device_type,
2601
2602 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data, character);
2603
2604 struct MessageData {
2606 void* user_data;
2607 };
2608
2609 MessageData* message_data =
2610 new MessageData{.callback = callback, .user_data = user_data};
2611
2613 engine, kFlutterKeyDataChannel, packet->data().data(),
2614 packet->data().size(),
2615 [](const uint8_t* data, size_t size, void* user_data) {
2616 auto message_data = std::unique_ptr<MessageData>(
2617 reinterpret_cast<MessageData*>(user_data));
2618 if (message_data->callback == nullptr) {
2619 return;
2620 }
2621 bool handled = false;
2622 if (size == 1) {
2623 handled = *data != 0;
2624 }
2625 message_data->callback(handled, message_data->user_data);
2626 },
2627 message_data);
2628}

◆ FlutterEngineSendPlatformMessage()

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

Definition at line 2630 of file embedder.cc.

2632 {
2633 if (engine == nullptr) {
2634 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2635 }
2636
2637 if (flutter_message == nullptr) {
2638 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid message argument.");
2639 }
2640
2641 if (SAFE_ACCESS(flutter_message, channel, nullptr) == nullptr) {
2642 return LOG_EMBEDDER_ERROR(
2643 kInvalidArguments, "Message argument did not specify a valid channel.");
2644 }
2645
2646 size_t message_size = SAFE_ACCESS(flutter_message, message_size, 0);
2647 const uint8_t* message_data = SAFE_ACCESS(flutter_message, message, nullptr);
2648
2649 if (message_size != 0 && message_data == nullptr) {
2650 return LOG_EMBEDDER_ERROR(
2652 "Message size was non-zero but the message data was nullptr.");
2653 }
2654
2655 const FlutterPlatformMessageResponseHandle* response_handle =
2656 SAFE_ACCESS(flutter_message, response_handle, nullptr);
2657
2659 if (response_handle && response_handle->message) {
2660 response = response_handle->message->response();
2661 }
2662
2663 std::unique_ptr<flutter::PlatformMessage> message;
2664 if (message_size == 0) {
2665 message = std::make_unique<flutter::PlatformMessage>(
2666 flutter_message->channel, response);
2667 } else {
2668 message = std::make_unique<flutter::PlatformMessage>(
2669 flutter_message->channel,
2670 fml::MallocMapping::Copy(message_data, message_size), response);
2671 }
2672
2673 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2674 ->SendPlatformMessage(std::move(message))
2675 ? kSuccess
2677 "Could not send a message to the running "
2678 "Flutter application.");
2679}

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

2735 {
2736 if (data_length != 0 && data == nullptr) {
2737 return LOG_EMBEDDER_ERROR(
2739 "Data size was non zero but the pointer to the data was null.");
2740 }
2741
2742 auto response = handle->message->response();
2743
2744 if (response) {
2745 if (data_length == 0) {
2746 response->CompleteEmpty();
2747 } else {
2748 response->Complete(std::make_unique<fml::DataMapping>(
2749 std::vector<uint8_t>({data, data + data_length})));
2750 }
2751 }
2752
2753 delete handle;
2754
2755 return kSuccess;
2756}

◆ FlutterEngineSendPointerEvent()

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

Definition at line 2423 of file embedder.cc.

2426 {
2427 if (engine == nullptr) {
2428 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2429 }
2430
2431 if (pointers == nullptr || events_count == 0) {
2432 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid pointer events.");
2433 }
2434
2435 auto packet = std::make_unique<flutter::PointerDataPacket>(events_count);
2436
2437 const FlutterPointerEvent* current = pointers;
2438
2439 for (size_t i = 0; i < events_count; ++i) {
2440 flutter::PointerData pointer_data;
2441 pointer_data.Clear();
2442 // this is currely in use only on android embedding.
2443 pointer_data.embedder_id = 0;
2444 pointer_data.time_stamp = SAFE_ACCESS(current, timestamp, 0);
2445 pointer_data.change = ToPointerDataChange(
2446 SAFE_ACCESS(current, phase, FlutterPointerPhase::kCancel));
2447 pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
2448 pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
2449 // Delta will be generated in pointer_data_packet_converter.cc.
2450 pointer_data.physical_delta_x = 0.0;
2451 pointer_data.physical_delta_y = 0.0;
2452 pointer_data.device = SAFE_ACCESS(current, device, 0);
2453 // Pointer identifier will be generated in
2454 // pointer_data_packet_converter.cc.
2455 pointer_data.pointer_identifier = 0;
2456 pointer_data.signal_kind = ToPointerDataSignalKind(
2457 SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
2458 pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
2459 pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
2460 FlutterPointerDeviceKind device_kind =
2461 SAFE_ACCESS(current, device_kind, kFlutterPointerDeviceKindMouse);
2462 // For backwards compatibility with embedders written before the device
2463 // kind and buttons were exposed, if the device kind is not set treat it
2464 // as a mouse, with a synthesized primary button state based on the phase.
2465 if (device_kind == 0) {
2467 pointer_data.buttons =
2469
2470 } else {
2471 pointer_data.kind = ToPointerDataKind(device_kind);
2472 if (pointer_data.kind == flutter::PointerData::DeviceKind::kTouch) {
2473 // For touch events, set the button internally rather than requiring
2474 // it at the API level, since it's a confusing construction to expose.
2475 if (pointer_data.change == flutter::PointerData::Change::kDown ||
2478 }
2479 } else {
2480 // Buttons use the same mask values, so pass them through directly.
2481 pointer_data.buttons = SAFE_ACCESS(current, buttons, 0);
2482 }
2483 }
2484 pointer_data.pan_x = SAFE_ACCESS(current, pan_x, 0.0);
2485 pointer_data.pan_y = SAFE_ACCESS(current, pan_y, 0.0);
2486 // Delta will be generated in pointer_data_packet_converter.cc.
2487 pointer_data.pan_delta_x = 0.0;
2488 pointer_data.pan_delta_y = 0.0;
2489 pointer_data.scale = SAFE_ACCESS(current, scale, 0.0);
2490 pointer_data.rotation = SAFE_ACCESS(current, rotation, 0.0);
2491 pointer_data.view_id =
2492 SAFE_ACCESS(current, view_id, kFlutterImplicitViewId);
2493 packet->SetPointerData(i, pointer_data);
2494 current = reinterpret_cast<const FlutterPointerEvent*>(
2495 reinterpret_cast<const uint8_t*>(current) + current->struct_size);
2496 }
2497
2498 return reinterpret_cast<flutter::EmbedderEngine*>(engine)
2499 ->DispatchPointerDataPacket(std::move(packet))
2500 ? kSuccess
2502 "Could not dispatch pointer events to the "
2503 "running Flutter application.");
2504}

◆ FlutterEngineSendWindowMetricsEvent()

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

Definition at line 2314 of file embedder.cc.

2316 {
2317 if (engine == nullptr || flutter_metrics == nullptr) {
2318 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2319 }
2320 FlutterViewId view_id =
2321 SAFE_ACCESS(flutter_metrics, view_id, kFlutterImplicitViewId);
2322
2323 std::variant<flutter::ViewportMetrics, std::string> metrics_or_error =
2324 MakeViewportMetricsFromWindowMetrics(flutter_metrics);
2325 if (const std::string* error = std::get_if<std::string>(&metrics_or_error)) {
2326 return LOG_EMBEDDER_ERROR(kInvalidArguments, error->c_str());
2327 }
2328
2329 auto metrics = std::get<flutter::ViewportMetrics>(metrics_or_error);
2330
2331 return reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetViewportMetrics(
2332 view_id, metrics)
2333 ? kSuccess
2335 "Viewport metrics were invalid.");
2336}

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

3302 {
3303 if (engine == nullptr) {
3304 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3305 }
3306
3307 if (callback == nullptr) {
3309 "Next frame callback was null.");
3310 }
3311
3312 flutter::EmbedderEngine* embedder_engine =
3313 reinterpret_cast<flutter::EmbedderEngine*>(engine);
3314
3315 fml::WeakPtr<flutter::PlatformView> weak_platform_view =
3316 embedder_engine->GetShell().GetPlatformView();
3317
3318 if (!weak_platform_view) {
3320 "Platform view unavailable.");
3321 }
3322
3323 weak_platform_view->SetNextFrameCallback(
3325
3326 return kSuccess;
3327}

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

2304 {
2306 if (result != kSuccess) {
2307 return result;
2308 }
2309 auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
2310 delete embedder_engine;
2311 return kSuccess;
2312}

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

2913 {
2914 fml::tracing::TraceEvent0("flutter", name, /*flow_id_count=*/0,
2915 /*flow_ids=*/nullptr);
2916}

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

2918 {
2920}

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

2922 {
2923 fml::tracing::TraceEventInstant0("flutter", name, /*flow_id_count=*/0,
2924 /*flow_ids=*/nullptr);
2925}

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

2784 {
2785 if (engine == nullptr) {
2786 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2787 }
2788
2789 if (texture_identifier == 0) {
2791 "Texture identifier was invalid.");
2792 }
2793
2794 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->UnregisterTexture(
2795 texture_identifier)) {
2797 "Could not un-register the specified texture.");
2798 }
2799
2800 return kSuccess;
2801}

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

2837 {
2838 if (engine == nullptr) {
2839 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2840 }
2841 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
2842 ->SetAccessibilityFeatures(flags)) {
2844 "Could not update accessibility features.");
2845 }
2846 return kSuccess;
2847}

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

3001 {
3002 if (engine == nullptr) {
3003 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
3004 }
3005
3006 if (locales_count == 0) {
3007 return kSuccess;
3008 }
3009
3010 if (locales == nullptr) {
3011 return LOG_EMBEDDER_ERROR(kInvalidArguments, "No locales were specified.");
3012 }
3013
3014 rapidjson::Document document;
3015 auto& allocator = document.GetAllocator();
3016
3017 document.SetObject();
3018 document.AddMember("method", "setLocale", allocator);
3019
3020 rapidjson::Value args(rapidjson::kArrayType);
3021 args.Reserve(locales_count * 4, allocator);
3022 for (size_t i = 0; i < locales_count; ++i) {
3023 const FlutterLocale* locale = locales[i];
3024 const char* language_code_str = SAFE_ACCESS(locale, language_code, nullptr);
3025 if (language_code_str == nullptr || ::strlen(language_code_str) == 0) {
3026 return LOG_EMBEDDER_ERROR(
3028 "Language code is required but not present in FlutterLocale.");
3029 }
3030
3031 const char* country_code_str = SAFE_ACCESS(locale, country_code, "");
3032 const char* script_code_str = SAFE_ACCESS(locale, script_code, "");
3033 const char* variant_code_str = SAFE_ACCESS(locale, variant_code, "");
3034
3035 rapidjson::Value language_code, country_code, script_code, variant_code;
3036
3037 language_code.SetString(language_code_str, allocator);
3038 country_code.SetString(country_code_str ? country_code_str : "", allocator);
3039 script_code.SetString(script_code_str ? script_code_str : "", allocator);
3040 variant_code.SetString(variant_code_str ? variant_code_str : "", allocator);
3041
3042 // Required.
3043 args.PushBack(language_code, allocator);
3044 args.PushBack(country_code, allocator);
3045 args.PushBack(script_code, allocator);
3046 args.PushBack(variant_code, allocator);
3047 }
3048 document.AddMember("args", args, allocator);
3049
3050 return DispatchJSONPlatformMessage(engine, document, "flutter/localization")
3051 ? kSuccess
3053 "Could not send message to update locale of "
3054 "a running Flutter application.");
3055}

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

2823 {
2824 if (engine == nullptr) {
2825 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2826 }
2827 if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)->SetSemanticsEnabled(
2828 enabled)) {
2830 "Could not update semantics state.");
2831 }
2832 return kSuccess;
2833}

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

2685 {
2686 if (engine == nullptr) {
2687 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
2688 }
2689
2690 if (data_callback == nullptr || response_out == nullptr) {
2691 return LOG_EMBEDDER_ERROR(
2692 kInvalidArguments, "Data callback or the response handle was invalid.");
2693 }
2694
2696 [user_data, data_callback](const uint8_t* data, size_t size) {
2697 data_callback(data, size, user_data);
2698 };
2699
2700 auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
2701 ->GetTaskRunners()
2702 .GetPlatformTaskRunner();
2703
2704 auto handle = new FlutterPlatformMessageResponseHandle();
2705
2706 handle->message = std::make_unique<flutter::PlatformMessage>(
2707 "", // The channel is empty and unused as the response handle is going
2708 // to referenced directly in the |FlutterEngineSendPlatformMessage|
2709 // with the container message discarded.
2710 fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
2711 std::move(platform_task_runner), response_callback));
2712 *response_out = handle;
2713 return kSuccess;
2714}

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

2718 {
2719 if (engine == nullptr) {
2720 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid engine handle.");
2721 }
2722
2723 if (response == nullptr) {
2724 return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid response handle.");
2725 }
2726 delete response;
2727 return kSuccess;
2728}

◆ InferExternalViewEmbedderFromArgs()

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

Definition at line 1279 of file embedder.cc.

1280 {
1281 if (compositor == nullptr) {
1282 return {nullptr, false};
1283 }
1284
1285 auto c_create_callback =
1286 SAFE_ACCESS(compositor, create_backing_store_callback, nullptr);
1287 auto c_collect_callback =
1288 SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr);
1289 auto c_present_callback =
1290 SAFE_ACCESS(compositor, present_layers_callback, nullptr);
1291 auto c_present_view_callback =
1292 SAFE_ACCESS(compositor, present_view_callback, nullptr);
1293 bool avoid_backing_store_cache =
1294 SAFE_ACCESS(compositor, avoid_backing_store_cache, false);
1295
1296 // Make sure the required callbacks are present
1297 if (!c_create_callback || !c_collect_callback) {
1298 FML_LOG(ERROR) << "Required compositor callbacks absent.";
1299 return {nullptr, true};
1300 }
1301 // Either the present view or the present layers callback must be provided.
1302 if ((!c_present_view_callback && !c_present_callback) ||
1303 (c_present_view_callback && c_present_callback)) {
1304 FML_LOG(ERROR) << "Either present_layers_callback or present_view_callback "
1305 "must be provided but not both.";
1306 return {nullptr, true};
1307 }
1308
1309 FlutterCompositor captured_compositor = *compositor;
1310
1312 create_render_target_callback =
1313 [captured_compositor, enable_impeller](
1314 GrDirectContext* context,
1315 const std::shared_ptr<impeller::AiksContext>& aiks_context,
1316 const auto& config) {
1317 return CreateEmbedderRenderTarget(&captured_compositor, config,
1318 context, aiks_context,
1319 enable_impeller);
1320 };
1321
1323 if (c_present_callback) {
1324 present_callback = [c_present_callback, user_data = compositor->user_data](
1325 FlutterViewId view_id, const auto& layers) {
1326 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1327 return c_present_callback(const_cast<const FlutterLayer**>(layers.data()),
1328 layers.size(), user_data);
1329 };
1330 } else {
1331 FML_DCHECK(c_present_view_callback != nullptr);
1332 present_callback = [c_present_view_callback,
1333 user_data = compositor->user_data](
1334 FlutterViewId view_id, const auto& layers) {
1335 TRACE_EVENT0("flutter", "FlutterCompositorPresentLayers");
1336
1339 .view_id = view_id,
1340 .layers = const_cast<const FlutterLayer**>(layers.data()),
1341 .layers_count = layers.size(),
1342 .user_data = user_data,
1343 };
1344
1345 return c_present_view_callback(&info);
1346 };
1347 }
1348
1349 return {std::make_unique<flutter::EmbedderExternalViewEmbedder>(
1350 avoid_backing_store_cache, create_render_target_callback,
1351 present_callback),
1352 false};
1353}

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

Definition at line 495 of file embedder.cc.

502 {
503 if (config->type != kMetal) {
504 return nullptr;
505 }
506
507#ifdef SHELL_ENABLE_METAL
508 std::function<bool(flutter::GPUMTLTextureInfo texture)> metal_present =
509 [ptr = config->metal.present_drawable_callback,
511 FlutterMetalTexture embedder_texture;
512 embedder_texture.struct_size = sizeof(FlutterMetalTexture);
513 embedder_texture.texture = texture.texture;
514 embedder_texture.texture_id = texture.texture_id;
515 embedder_texture.user_data = texture.destruction_context;
516 embedder_texture.destruction_callback = texture.destruction_callback;
517 return ptr(user_data, &embedder_texture);
518 };
519 auto metal_get_texture =
520 [ptr = config->metal.get_next_drawable_callback,
521 user_data](const SkISize& frame_size) -> flutter::GPUMTLTextureInfo {
522 FlutterFrameInfo frame_info = {};
523 frame_info.struct_size = sizeof(FlutterFrameInfo);
524 frame_info.size = {static_cast<uint32_t>(frame_size.width()),
525 static_cast<uint32_t>(frame_size.height())};
526 flutter::GPUMTLTextureInfo texture_info;
527
528 FlutterMetalTexture metal_texture = ptr(user_data, &frame_info);
529 texture_info.texture_id = metal_texture.texture_id;
530 texture_info.texture = metal_texture.texture;
531 texture_info.destruction_callback = metal_texture.destruction_callback;
532 texture_info.destruction_context = metal_texture.user_data;
533 return texture_info;
534 };
535
536 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
537 std::move(external_view_embedder);
538
539 std::unique_ptr<flutter::EmbedderSurface> embedder_surface;
540
541 if (enable_impeller) {
543 metal_dispatch_table = {
544 .present = metal_present,
545 .get_texture = metal_get_texture,
546 };
547 embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetalImpeller>(
548 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
551 metal_dispatch_table, view_embedder);
552 } else {
554 .present = metal_present,
555 .get_texture = metal_get_texture,
556 };
557 embedder_surface = std::make_unique<flutter::EmbedderSurfaceMetal>(
558 const_cast<flutter::GPUMTLDeviceHandle>(config->metal.device),
561 metal_dispatch_table, view_embedder);
562 }
563
564 // The static leak checker gets confused by the use of fml::MakeCopyable.
565 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
566 return fml::MakeCopyable(
567 [embedder_surface = std::move(embedder_surface), platform_dispatch_table,
568 external_view_embedder = view_embedder](flutter::Shell& shell) mutable {
569 return std::make_unique<flutter::PlatformViewEmbedder>(
570 shell, // delegate
571 shell.GetTaskRunners(), // task runners
572 std::move(embedder_surface), // embedder surface
573 platform_dispatch_table, // platform dispatch table
574 std::move(external_view_embedder) // external view embedder
575 );
576 });
577#else
578 return nullptr;
579#endif
580}

◆ 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 
)
inlinestatic

Definition at line 283 of file embedder.cc.

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

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

Definition at line 707 of file embedder.cc.

714 {
715 if (config == nullptr) {
716 return nullptr;
717 }
718
719 switch (config->type) {
720 case kOpenGL:
722 config, user_data, platform_dispatch_table,
723 std::move(external_view_embedder), enable_impeller);
724 case kSoftware:
726 config, user_data, platform_dispatch_table,
727 std::move(external_view_embedder));
728 case kMetal:
730 config, user_data, platform_dispatch_table,
731 std::move(external_view_embedder), enable_impeller);
732 case kVulkan:
734 config, user_data, platform_dispatch_table,
735 std::move(external_view_embedder));
736 default:
737 return nullptr;
738 }
739 return nullptr;
740}

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

676 {
677 if (config->type != kSoftware) {
678 return nullptr;
679 }
680
681 auto software_present_backing_store =
683 const void* allocation, size_t row_bytes, size_t height) -> bool {
684 return ptr(user_data, allocation, row_bytes, height);
685 };
686
688 software_dispatch_table = {
689 software_present_backing_store, // required
690 };
691
692 return fml::MakeCopyable(
693 [software_dispatch_table, platform_dispatch_table,
694 external_view_embedder =
695 std::move(external_view_embedder)](flutter::Shell& shell) mutable {
696 return std::make_unique<flutter::PlatformViewEmbedder>(
697 shell, // delegate
698 shell.GetTaskRunners(), // task runners
699 software_dispatch_table, // software dispatch table
700 platform_dispatch_table, // platform dispatch table
701 std::move(external_view_embedder) // external view embedder
702 );
703 });
704}

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

Definition at line 583 of file embedder.cc.

589 {
590 if (config->type != kVulkan) {
591 return nullptr;
592 }
593
594#ifdef SHELL_ENABLE_VULKAN
595 std::function<void*(VkInstance, const char*)>
596 vulkan_get_instance_proc_address =
598 VkInstance instance, const char* proc_name) -> void* {
599 return ptr(user_data, instance, proc_name);
600 };
601
602 auto vulkan_get_next_image =
603 [ptr = config->vulkan.get_next_image_callback,
604 user_data](const SkISize& frame_size) -> FlutterVulkanImage {
605 FlutterFrameInfo frame_info = {
606 .struct_size = sizeof(FlutterFrameInfo),
607 .size = {static_cast<uint32_t>(frame_size.width()),
608 static_cast<uint32_t>(frame_size.height())},
609 };
610
611 return ptr(user_data, &frame_info);
612 };
613
614 auto vulkan_present_image_callback =
615 [ptr = config->vulkan.present_image_callback, user_data](
616 VkImage image, VkFormat format) -> bool {
617 FlutterVulkanImage image_desc = {
619 .image = reinterpret_cast<uint64_t>(image),
620 .format = static_cast<uint32_t>(format),
621 };
622 return ptr(user_data, &image_desc);
623 };
624
625 auto vk_instance = static_cast<VkInstance>(config->vulkan.instance);
626 auto proc_addr =
627 vulkan_get_instance_proc_address(vk_instance, "vkGetInstanceProcAddr");
628
631 reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
632 .get_next_image = vulkan_get_next_image,
633 .present_image = vulkan_present_image_callback,
634 };
635
636 std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
637 std::move(external_view_embedder);
638
639 std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
640 std::make_unique<flutter::EmbedderSurfaceVulkan>(
641 config->vulkan.version, vk_instance,
646 static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
647 static_cast<VkDevice>(config->vulkan.device),
649 static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
650 view_embedder);
651
652 return fml::MakeCopyable(
653 [embedder_surface = std::move(embedder_surface), platform_dispatch_table,
654 external_view_embedder =
655 std::move(view_embedder)](flutter::Shell& shell) mutable {
656 return std::make_unique<flutter::PlatformViewEmbedder>(
657 shell, // delegate
658 shell.GetTaskRunners(), // task runners
659 std::move(embedder_surface), // embedder surface
660 platform_dispatch_table, // platform dispatch table
661 std::move(external_view_embedder) // external view embedder
662 );
663 });
664#else
665 return nullptr;
666#endif
667}

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

2545 {
2547
2548 FlutterPlatformMessageResponseHandle* response_handle;
2550 engine, data_callback, user_data, &response_handle);
2551 if (result != kSuccess) {
2552 return result;
2553 }
2554
2556 sizeof(FlutterPlatformMessage), // struct_size
2557 channel, // channel
2558 data, // message
2559 size, // message_size
2560 response_handle, // response_handle
2561 };
2562
2564 // Whether `SendPlatformMessage` succeeds or not, the response handle must be
2565 // released.
2566 FlutterEngineResult release_result =
2568 if (result != kSuccess) {
2569 return result;
2570 }
2571
2572 return release_result;
2573}

◆ IsMetalRendererConfigValid()

static bool IsMetalRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 188 of file embedder.cc.

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

◆ IsOpenGLRendererConfigValid()

static bool IsOpenGLRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 155 of file embedder.cc.

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

◆ IsRendererValid()

static bool IsRendererValid ( const FlutterRendererConfig config)
static

Definition at line 226 of file embedder.cc.

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

◆ IsSoftwareRendererConfigValid()

static bool IsSoftwareRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 173 of file embedder.cc.

173 {
174 if (config->type != kSoftware) {
175 return false;
176 }
177
178 const FlutterSoftwareRendererConfig* software_config = &config->software;
179
180 if (SAFE_ACCESS(software_config, surface_present_callback, nullptr) ==
181 nullptr) {
182 return false;
183 }
184
185 return true;
186}

◆ IsVulkanRendererConfigValid()

static bool IsVulkanRendererConfigValid ( const FlutterRendererConfig config)
static

Definition at line 206 of file embedder.cc.

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

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

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

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

1038 {
1039#if defined(SHELL_ENABLE_METAL) && defined(IMPELLER_SUPPORTS_RENDERING)
1040 if (!metal->texture.texture) {
1041 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
1042 return nullptr;
1043 }
1044
1045 const auto size = impeller::ISize(config.size.width, config.size.height);
1046
1047 impeller::TextureDescriptor resolve_tex_desc;
1048 resolve_tex_desc.size = size;
1051 resolve_tex_desc.usage = impeller::TextureUsage::kRenderTarget |
1053
1054 auto resolve_tex = impeller::WrapTextureMTL(
1055 resolve_tex_desc, metal->texture.texture,
1057 user_data = metal->texture.user_data]() { callback(user_data); });
1058 if (!resolve_tex) {
1059 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
1060 return nullptr;
1061 }
1062 resolve_tex->SetLabel("ImpellerBackingStoreResolve");
1063
1064 impeller::TextureDescriptor msaa_tex_desc;
1068 msaa_tex_desc.format = resolve_tex->GetTextureDescriptor().format;
1069 msaa_tex_desc.size = size;
1071
1072 auto msaa_tex =
1073 aiks_context->GetContext()->GetResourceAllocator()->CreateTexture(
1074 msaa_tex_desc);
1075 if (!msaa_tex) {
1076 FML_LOG(ERROR) << "Could not allocate MSAA color texture.";
1077 return nullptr;
1078 }
1079 msaa_tex->SetLabel("ImpellerBackingStoreColorMSAA");
1080
1082 color0.texture = msaa_tex;
1086 color0.resolve_texture = resolve_tex;
1087
1088 impeller::RenderTarget render_target_desc;
1089 render_target_desc.SetColorAttachment(color0, 0u);
1090
1091 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1092 backing_store, aiks_context,
1093 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1094 on_release, fml::closure());
1095#else
1096 return nullptr;
1097#endif
1098}

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

966 {
967#if defined(SHELL_ENABLE_GL) && defined(IMPELLER_SUPPORTS_RENDERING)
968
969 const auto& gl_context =
970 impeller::ContextGLES::Cast(*aiks_context->GetContext());
971 const auto size = impeller::ISize(config.size.width, config.size.height);
972
976 color0_tex.size = size;
977 color0_tex.usage = static_cast<impeller::TextureUsageMask>(
981
984 gl_context.GetReactor(), color0_tex, framebuffer->name);
988
989 impeller::TextureDescriptor depth_stencil_texture_desc;
990 depth_stencil_texture_desc.type = impeller::TextureType::kTexture2D;
991 depth_stencil_texture_desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt;
992 depth_stencil_texture_desc.size = size;
993 depth_stencil_texture_desc.usage = static_cast<impeller::TextureUsageMask>(
995 depth_stencil_texture_desc.sample_count = impeller::SampleCount::kCount1;
996
997 auto depth_stencil_tex = std::make_shared<impeller::TextureGLES>(
998 gl_context.GetReactor(), depth_stencil_texture_desc,
1000
1002 depth0.clear_depth = 0;
1003 depth0.texture = depth_stencil_tex;
1006
1008 stencil0.clear_stencil = 0;
1009 stencil0.texture = depth_stencil_tex;
1012
1013 impeller::RenderTarget render_target_desc;
1014
1015 render_target_desc.SetColorAttachment(color0, 0u);
1016 render_target_desc.SetDepthAttachment(depth0);
1017 render_target_desc.SetStencilAttachment(stencil0);
1018
1019 fml::closure framebuffer_destruct =
1020 [callback = framebuffer->destruction_callback,
1021 user_data = framebuffer->user_data]() { callback(user_data); };
1022
1023 return std::make_unique<flutter::EmbedderRenderTargetImpeller>(
1024 backing_store, aiks_context,
1025 std::make_unique<impeller::RenderTarget>(std::move(render_target_desc)),
1026 on_release, framebuffer_destruct);
1027#else
1028 return nullptr;
1029#endif
1030}

◆ MakeRenderTargetFromSkSurface()

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

Definition at line 1152 of file embedder.cc.

1154 {
1155 if (!skia_surface) {
1156 return nullptr;
1157 }
1158 return std::make_unique<flutter::EmbedderRenderTargetSkia>(
1159 backing_store, std::move(skia_surface), std::move(on_release));
1160}

◆ MakeSkSurfaceFromBackingStore() [1/6]

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

Definition at line 912 of file embedder.cc.

915 {
916#ifdef SHELL_ENABLE_METAL
917 GrMtlTextureInfo texture_info;
918 if (!metal->texture.texture) {
919 FML_LOG(ERROR) << "Embedder supplied null Metal texture.";
920 return nullptr;
921 }
922 sk_cfp<FlutterMetalTextureHandle> mtl_texture;
923 mtl_texture.retain(metal->texture.texture);
924 texture_info.fTexture = mtl_texture;
925 GrBackendTexture backend_texture =
927 config.size.height, //
928 skgpu::Mipmapped::kNo, //
929 texture_info //
930 );
931
932 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
933
935 context, // context
936 backend_texture, // back-end texture
937 kTopLeft_GrSurfaceOrigin, // surface origin
938 // TODO(dnfield): Update this when embedders support MSAA, see
939 // https://github.com/flutter/flutter/issues/100392
940 1, // sample count
941 kBGRA_8888_SkColorType, // color type
942 nullptr, // color space
943 &surface_properties, // surface properties
945 metal->texture.destruction_callback), // release proc
946 metal->texture.user_data // release context
947 );
948
949 if (!surface) {
950 FML_LOG(ERROR) << "Could not wrap embedder supplied Metal render texture.";
951 return nullptr;
952 }
953
954 return surface;
955#else
956 return nullptr;
957#endif
958}

◆ MakeSkSurfaceFromBackingStore() [2/6]

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

Definition at line 782 of file embedder.cc.

785 {
786#ifdef SHELL_ENABLE_GL
787 GrGLFramebufferInfo framebuffer_info = {};
788 framebuffer_info.fFormat = framebuffer->target;
789 framebuffer_info.fFBOID = framebuffer->name;
790
791 auto backend_render_target =
793 config.size.height, // height
794 1, // sample count
795 0, // stencil bits
796 framebuffer_info // framebuffer info
797 );
798
799 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
800
802 context, // context
803 backend_render_target, // backend render target
804 kBottomLeft_GrSurfaceOrigin, // surface origin
805 kN32_SkColorType, // color type
806 SkColorSpace::MakeSRGB(), // color space
807 &surface_properties, // surface properties
809 framebuffer->destruction_callback), // release proc
810 framebuffer->user_data // release context
811 );
812
813 if (!surface) {
814 FML_LOG(ERROR) << "Could not wrap embedder supplied frame-buffer.";
815 return nullptr;
816 }
817 return surface;
818#else
819 return nullptr;
820#endif
821}

◆ MakeSkSurfaceFromBackingStore() [3/6]

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

Definition at line 742 of file embedder.cc.

745 {
746#ifdef SHELL_ENABLE_GL
747 GrGLTextureInfo texture_info;
748 texture_info.fTarget = texture->target;
749 texture_info.fID = texture->name;
750 texture_info.fFormat = texture->format;
751
752 GrBackendTexture backend_texture =
754 skgpu::Mipmapped::kNo, texture_info);
755
756 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
757
759 context, // context
760 backend_texture, // back-end texture
761 kBottomLeft_GrSurfaceOrigin, // surface origin
762 1, // sample count
763 kN32_SkColorType, // color type
764 SkColorSpace::MakeSRGB(), // color space
765 &surface_properties, // surface properties
767 texture->destruction_callback), // release proc
768 texture->user_data // release context
769 );
770
771 if (!surface) {
772 FML_LOG(ERROR) << "Could not wrap embedder supplied render texture.";
773 return nullptr;
774 }
775
776 return surface;
777#else
778 return nullptr;
779#endif
780}

◆ MakeSkSurfaceFromBackingStore() [4/6]

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

Definition at line 823 of file embedder.cc.

826 {
827 const auto image_info =
829
830 struct Captures {
831 VoidCallback destruction_callback;
832 void* user_data;
833 };
834 auto captures = std::make_unique<Captures>();
835 captures->destruction_callback = software->destruction_callback;
836 captures->user_data = software->user_data;
837 auto release_proc = [](void* pixels, void* context) {
838 auto captures = reinterpret_cast<Captures*>(context);
839 if (captures->destruction_callback) {
840 captures->destruction_callback(captures->user_data);
841 }
842 delete captures;
843 };
844
845 auto surface =
846 SkSurfaces::WrapPixels(image_info, // image info
847 const_cast<void*>(software->allocation), // pixels
848 software->row_bytes, // row bytes
849 release_proc, // release proc
850 captures.get() // get context
851 );
852
853 if (!surface) {
855 << "Could not wrap embedder supplied software render buffer.";
856 if (software->destruction_callback) {
857 software->destruction_callback(software->user_data);
858 }
859 return nullptr;
860 }
861 if (surface) {
862 captures.release(); // Skia has assumed ownership of the struct.
863 }
864 return surface;
865}

◆ MakeSkSurfaceFromBackingStore() [5/6]

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

Definition at line 867 of file embedder.cc.

870 {
871 const auto color_info = getSkColorInfo(software->pixel_format);
872 if (!color_info) {
873 return nullptr;
874 }
875
876 const auto image_info = SkImageInfo::Make(
877 SkISize::Make(config.size.width, config.size.height), *color_info);
878
879 struct Captures {
880 VoidCallback destruction_callback;
881 void* user_data;
882 };
883 auto captures = std::make_unique<Captures>();
884 captures->destruction_callback = software->destruction_callback;
885 captures->user_data = software->user_data;
886 auto release_proc = [](void* pixels, void* context) {
887 auto captures = reinterpret_cast<Captures*>(context);
888 if (captures->destruction_callback) {
889 captures->destruction_callback(captures->user_data);
890 }
891 };
892
893 auto surface =
894 SkSurfaces::WrapPixels(image_info, // image info
895 const_cast<void*>(software->allocation), // pixels
896 software->row_bytes, // row bytes
897 release_proc, // release proc
898 captures.release() // release context
899 );
900
901 if (!surface) {
903 << "Could not wrap embedder supplied software render buffer.";
904 if (software->destruction_callback) {
905 software->destruction_callback(software->user_data);
906 }
907 return nullptr;
908 }
909 return surface;
910}

◆ MakeSkSurfaceFromBackingStore() [6/6]

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

Definition at line 1100 of file embedder.cc.

1103 {
1104#ifdef SHELL_ENABLE_VULKAN
1105 if (!vulkan->image) {
1106 FML_LOG(ERROR) << "Embedder supplied null Vulkan image.";
1107 return nullptr;
1108 }
1109 GrVkImageInfo image_info = {
1110 .fImage = reinterpret_cast<VkImage>(vulkan->image->image),
1111 .fImageTiling = VK_IMAGE_TILING_OPTIMAL,
1112 .fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1113 .fFormat = static_cast<VkFormat>(vulkan->image->format),
1114 .fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1118 .fSampleCount = 1,
1119 .fLevelCount = 1,
1120 };
1121 auto backend_texture = GrBackendTextures::MakeVk(
1122 config.size.width, config.size.height, image_info);
1123
1124 SkSurfaceProps surface_properties(0, kUnknown_SkPixelGeometry);
1125
1127 context, // context
1128 backend_texture, // back-end texture
1129 kTopLeft_GrSurfaceOrigin, // surface origin
1130 1, // sample count
1132 static_cast<VkFormat>(vulkan->image->format)), // color type
1133 SkColorSpace::MakeSRGB(), // color space
1134 &surface_properties, // surface properties
1135 static_cast<SkSurfaces::TextureReleaseProc>(
1136 vulkan->destruction_callback), // release proc
1137 vulkan->user_data // release context
1138 );
1139
1140 if (!surface) {
1141 FML_LOG(ERROR) << "Could not wrap embedder supplied Vulkan render texture.";
1142 return nullptr;
1143 }
1144
1145 return surface;
1146#else
1147 return nullptr;
1148#endif
1149}

◆ MakeViewportMetricsFromWindowMetrics()

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

Definition at line 1357 of file embedder.cc.

1358 {
1359 if (flutter_metrics == nullptr) {
1360 return "Invalid metrics handle.";
1361 }
1362
1364
1365 metrics.physical_width = SAFE_ACCESS(flutter_metrics, width, 0.0);
1366 metrics.physical_height = SAFE_ACCESS(flutter_metrics, height, 0.0);
1367 metrics.device_pixel_ratio = SAFE_ACCESS(flutter_metrics, pixel_ratio, 1.0);
1368 metrics.physical_view_inset_top =
1369 SAFE_ACCESS(flutter_metrics, physical_view_inset_top, 0.0);
1371 SAFE_ACCESS(flutter_metrics, physical_view_inset_right, 0.0);
1373 SAFE_ACCESS(flutter_metrics, physical_view_inset_bottom, 0.0);
1374 metrics.physical_view_inset_left =
1375 SAFE_ACCESS(flutter_metrics, physical_view_inset_left, 0.0);
1376 metrics.display_id = SAFE_ACCESS(flutter_metrics, display_id, 0);
1377
1378 if (metrics.device_pixel_ratio <= 0.0) {
1379 return "Device pixel ratio was invalid. It must be greater than zero.";
1380 }
1381
1382 if (metrics.physical_view_inset_top < 0 ||
1383 metrics.physical_view_inset_right < 0 ||
1384 metrics.physical_view_inset_bottom < 0 ||
1385 metrics.physical_view_inset_left < 0) {
1386 return "Physical view insets are invalid. They must be non-negative.";
1387 }
1388
1389 if (metrics.physical_view_inset_top > metrics.physical_height ||
1390 metrics.physical_view_inset_right > metrics.physical_width ||
1391 metrics.physical_view_inset_bottom > metrics.physical_height ||
1392 metrics.physical_view_inset_left > metrics.physical_width) {
1393 return "Physical view insets are invalid. They cannot be greater than "
1394 "physical height or width.";
1395 }
1396
1397 return metrics;
1398}

◆ MapKeyEventDeviceType()

static flutter::KeyEventDeviceType MapKeyEventDeviceType ( FlutterKeyEventDeviceType  event_kind)
inlinestatic

◆ MapKeyEventType()

static flutter::KeyEventType MapKeyEventType ( FlutterKeyEventType  event_kind)
inlinestatic

Definition at line 2506 of file embedder.cc.

2507 {
2508 switch (event_kind) {
2515 }
2517}

◆ PointerDataButtonsForLegacyEvent()

int64_t PointerDataButtonsForLegacyEvent ( flutter::PointerData::Change  change)
inline

Definition at line 2402 of file embedder.cc.

2403 {
2404 switch (change) {
2407 // These kinds of change must have a non-zero `buttons`, otherwise
2408 // gesture recognizers will ignore these events.
2418 return 0;
2419 }
2420 return 0;
2421}

◆ PopulateAOTSnapshotMappingCallbacks()

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

Definition at line 1532 of file embedder.cc.

1534 { // NOLINT(google-runtime-references)
1535 // There are no ownership concerns here as all mappings are owned by the
1536 // embedder and not the engine.
1537 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
1538 return [mapping, size]() {
1539 return std::make_unique<fml::NonOwnedMapping>(mapping, size);
1540 };
1541 };
1542
1543 if (SAFE_ACCESS(args, aot_data, nullptr) != nullptr) {
1544 settings.vm_snapshot_data =
1545 make_mapping_callback(args->aot_data->vm_snapshot_data, 0);
1546
1547 settings.vm_snapshot_instr =
1548 make_mapping_callback(args->aot_data->vm_snapshot_instrs, 0);
1549
1550 settings.isolate_snapshot_data =
1551 make_mapping_callback(args->aot_data->vm_isolate_data, 0);
1552
1553 settings.isolate_snapshot_instr =
1554 make_mapping_callback(args->aot_data->vm_isolate_instrs, 0);
1555 }
1556
1557 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1558 settings.vm_snapshot_data = make_mapping_callback(
1559 args->vm_snapshot_data, SAFE_ACCESS(args, vm_snapshot_data_size, 0));
1560 }
1561
1562 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1563 settings.vm_snapshot_instr = make_mapping_callback(
1564 args->vm_snapshot_instructions,
1565 SAFE_ACCESS(args, vm_snapshot_instructions_size, 0));
1566 }
1567
1568 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1569 settings.isolate_snapshot_data =
1570 make_mapping_callback(args->isolate_snapshot_data,
1571 SAFE_ACCESS(args, isolate_snapshot_data_size, 0));
1572 }
1573
1574 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1575 settings.isolate_snapshot_instr = make_mapping_callback(
1576 args->isolate_snapshot_instructions,
1577 SAFE_ACCESS(args, isolate_snapshot_instructions_size, 0));
1578 }
1579}

◆ PopulateJITSnapshotMappingCallbacks()

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

Definition at line 1489 of file embedder.cc.

1490 {
1491 auto make_mapping_callback = [](const char* path, bool executable) {
1492 return [path, executable]() {
1493 if (executable) {
1495 } else {
1497 }
1498 };
1499 };
1500
1501 // Users are allowed to specify only certain snapshots if they so desire.
1502 if (SAFE_ACCESS(args, vm_snapshot_data, nullptr) != nullptr) {
1503 settings.vm_snapshot_data = make_mapping_callback(
1504 reinterpret_cast<const char*>(args->vm_snapshot_data), false);
1505 }
1506
1507 if (SAFE_ACCESS(args, vm_snapshot_instructions, nullptr) != nullptr) {
1508 settings.vm_snapshot_instr = make_mapping_callback(
1509 reinterpret_cast<const char*>(args->vm_snapshot_instructions), true);
1510 }
1511
1512 if (SAFE_ACCESS(args, isolate_snapshot_data, nullptr) != nullptr) {
1513 settings.isolate_snapshot_data = make_mapping_callback(
1514 reinterpret_cast<const char*>(args->isolate_snapshot_data), false);
1515 }
1516
1517 if (SAFE_ACCESS(args, isolate_snapshot_instructions, nullptr) != nullptr) {
1518 settings.isolate_snapshot_instr = make_mapping_callback(
1519 reinterpret_cast<const char*>(args->isolate_snapshot_instructions),
1520 true);
1521 }
1522
1523#if !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
1524 settings.dart_library_sources_kernel = []() {
1525 return std::make_unique<fml::NonOwnedMapping>(kPlatformStrongDill,
1527 };
1528#endif // !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE ==
1529 // FLUTTER_RUNTIME_MODE_DEBUG)
1530}

◆ ToPointerDataChange()

flutter::PointerData::Change ToPointerDataChange ( FlutterPointerPhase  phase)
inline

Definition at line 2339 of file embedder.cc.

◆ ToPointerDataKind()

flutter::PointerData::DeviceKind ToPointerDataKind ( FlutterPointerDeviceKind  device_kind)
inline

◆ ToPointerDataSignalKind()

flutter::PointerData::SignalKind ToPointerDataSignalKind ( FlutterPointerSignalKind  kind)
inline

Variable Documentation

◆ kFlutterImplicitViewId

constexpr FlutterViewId kFlutterImplicitViewId = 0
staticconstexpr

Definition at line 107 of file embedder.cc.

◆ kFlutterKeyDataChannel

const char* kFlutterKeyDataChannel = "flutter/keydata"

Definition at line 129 of file embedder.cc.

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

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

◆ kPlatformStrongDill

const uint8_t kPlatformStrongDill[]
extern

◆ kPlatformStrongDillSize

const intptr_t kPlatformStrongDillSize
extern