浏览代码

Merge pull request #106 from Unity-Technologies/siyaoH/1.17/android

Siyao h/1.17/android
/siyaoH-1.17-PlatformMessage
GitHub 4 年前
当前提交
02eda9ee
共有 39 个文件被更改,包括 1912 次插入70 次删除
  1. 5
      Samples/UIWidgetsSamples_2019_4/Assets/CountDemo.cs
  2. 84
      Samples/UIWidgetsSamples_2019_4/Assets/CountDemo.unity
  3. 4
      Samples/UIWidgetsSamples_2019_4/Assets/Editor/EditorWindowSample/GalleryMain.cs
  4. 5
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/backdrop_demo.cs
  5. 12
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/search_demo.cs
  6. 5
      Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/backdrop.cs
  7. 24
      com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs
  8. 66
      com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanelWrapper.cs
  9. 1
      com.unity.uiwidgets/Runtime/foundation/debug.cs
  10. 1
      com.unity.uiwidgets/Runtime/material/material_state.cs
  11. 1
      com.unity.uiwidgets/Runtime/rendering/debug_overflow_indicator.cs
  12. 278
      engine/Build.bee.cs
  13. 63
      engine/README.md
  14. 16
      engine/src/assets/directory_asset_bundle.cc
  15. 1
      engine/src/engine.cc
  16. 16
      engine/src/flow/raster_cache.cc
  17. 11
      engine/src/lib/ui/painting/skottie.cc
  18. 2
      engine/src/lib/ui/text/paragraph.cc
  19. 5
      engine/src/runtime/mono_api.cc
  20. 2
      engine/src/shell/common/lists.cc
  21. 2
      engine/src/shell/gpu/gpu_surface_gl_delegate.cc
  22. 2
      engine/src/shell/platform/embedder/embedder_render_target.cc
  23. 2
      engine/src/shell/platform/embedder/embedder_surface_software.cc
  24. 2
      engine/src/shell/platform/unity/gfx_worker_task_runner.cc
  25. 4
      engine/src/shell/platform/unity/uiwidgets_system.h
  26. 45
      com.unity.uiwidgets/Runtime/engine2/AndroidPlatformUtil.cs
  27. 3
      com.unity.uiwidgets/Runtime/engine2/AndroidPlatformUtil.cs.meta
  28. 17
      engine/src/shell/platform/unity/android_unpack_streaming_asset.cc
  29. 16
      engine/src/shell/platform/unity/android_unpack_streaming_asset.h
  30. 94
      engine/src/shell/platform/unity/android/uiwidgets_system.cc
  31. 86
      engine/src/shell/platform/unity/android/uiwidgets_system.h
  32. 586
      engine/src/shell/platform/unity/android/uiwidgets_panel.cc
  33. 160
      engine/src/shell/platform/unity/android/unity_surface_manager.cc
  34. 63
      engine/src/shell/platform/unity/android/unity_surface_manager.h
  35. 113
      engine/src/shell/platform/unity/android/uiwidgets_panel.h
  36. 69
      engine/src/shell/platform/unity/android/android_task_runner.h
  37. 113
      engine/src/shell/platform/unity/android/android_task_runner.cc
  38. 3
      com.unity.uiwidgets/Runtime/service.meta

5
Samples/UIWidgetsSamples_2019_4/Assets/CountDemo.cs


using System.Collections.Generic;
using uiwidgets;
using UnityEngine.UI;
using Text = Unity.UIWidgets.widgets.Text;
using ui_ = Unity.UIWidgets.widgets.ui_;
using TextStyle = Unity.UIWidgets.painting.TextStyle;

child: new Column(children: new List<Widget>()
{
new Text($"count: {count}", style: new TextStyle(color: Color.fromARGB(255, 0 ,0 ,255))),
new Icon(CupertinoIcons.battery_charging, color: Colors.yellow),
new Text($"count: {count}", style: new TextStyle(fontFamily: "CupertixnoIcons", color: Color.fromARGB(255, 0 ,0 ,255))),
new Text($"count: {count}", style: new TextStyle(fontFamily: "CupertinoIcons", color: Color.fromARGB(255, 0 ,0 ,255))),
new CupertinoButton(
onPressed: () =>
{

84
Samples/UIWidgetsSamples_2019_4/Assets/CountDemo.unity


m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!28 &1096042013
Texture2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_ImageContentsHash:
serializedVersion: 2
Hash: 00000000000000000000000000000000
m_ForcedFallbackFormat: 4
m_DownscaleFallback: 0
serializedVersion: 2
m_Width: 0
m_Height: 0
m_CompleteImageSize: 0
m_TextureFormat: 0
m_MipCount: 1
m_IsReadable: 1
m_IgnoreMasterTextureLimit: 0
m_IsPreProcessed: 0
m_StreamingMipmaps: 0
m_StreamingMipmapsPriority: 0
m_AlphaIsTransparency: 0
m_ImageCount: 0
m_TextureDimension: 2
m_TextureSettings:
serializedVersion: 2
m_FilterMode: 1
m_Aniso: 1
m_MipBias: 0
m_WrapU: 0
m_WrapV: 0
m_WrapW: 0
m_LightmapFormat: 0
m_ColorSpace: 0
image data: 0
_typelessdata:
m_StreamData:
offset: 0
size: 0
path:
--- !u!1 &1344837310
GameObject:
m_ObjectHideFlags: 0

- component: {fileID: 1777874941}
- component: {fileID: 1777874942}
- component: {fileID: 1777874943}
- component: {fileID: 1777874944}
m_Layer: 5
m_Name: RawImage
m_TagString: Untagged

m_Father: {fileID: 314921623}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_SizeDelta: {x: 500, y: 500}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1777874942
CanvasRenderer:

m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1777874940}
m_Enabled: 1
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0817e3443c80cb943a03dcf7b120bd2e, type: 3}
m_Name:

y: 0
width: 1
height: 1
devicePixelRatioOverride: 0
hardwareAntiAliasing: 0
--- !u!114 &1777874944
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1777874940}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0817e3443c80cb943a03dcf7b120bd2e, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 1096042013}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
fonts:
- family: CupertinoIcons
fonts:
- asset: CupertinoIcons.ttf
weight: 0

4
Samples/UIWidgetsSamples_2019_4/Assets/Editor/EditorWindowSample/GalleryMain.cs


#if UNITY_EDITOR
using System.Collections.Generic;
using UIWidgetsGallery.gallery;
using Unity.UIWidgets.Editor;

ui_.runApp(new GalleryApp());
}
}
}
}
#endif

5
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/backdrop_demo.cs


{
new IconButton(
onPressed: this._toggleBackdropPanelVisibility,
icon: new AnimatedIcon(
icon: AnimatedIcons.close_menu,
progress: this._controller.view
icon: new Icon(
icon: Icons.close
)
)
}

12
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/material/search_demo.cs


appBar: new AppBar(
leading: new IconButton(
tooltip: "Navigation menu",
icon: new AnimatedIcon(
icon: AnimatedIcons.arrow_menu,
color: Colors.white,
progress: this._delegate.transitionAnimation
icon: new Icon(
icon: Icons.menu,
color: Colors.white
),
onPressed: () => { this._scaffoldKey.currentState.openDrawer(); }
),

public override Widget buildLeading(BuildContext context) {
return new IconButton(
tooltip: "Back",
icon: new AnimatedIcon(
icon: AnimatedIcons.arrow_menu,
progress: this.transitionAnimation
icon: new Icon(
icon: Icons.menu
),
onPressed: () => { this.close(context, null); }
);

5
Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/backdrop.cs


trailing: new IconButton(
onPressed: this._toggleFrontLayer,
tooltip: "Toggle options page",
icon: new AnimatedIcon(
icon: AnimatedIcons.close_menu,
progress: this._controller
icon: new Icon(
icon: Icons.close
)
)
),

24
com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanel.cs


Input_Update();
}
#if !UNITY_EDITOR && UNITY_ANDROID
bool AndroidInitialized = true;
IEnumerator DoInitAndroid() {
yield return new WaitForEndOfFrame();
AndroidPlatformUtil.Init();
yield return new WaitForEndOfFrame();
enabled = true;
}
bool IsAndroidInitialized() {
if (AndroidInitialized) {
enabled = false;
AndroidInitialized = false;
startCoroutine(DoInitAndroid());
return false;
}
return true;
}
#endif
#if !UNITY_EDITOR && UNITY_ANDROID
if (!IsAndroidInitialized()) {return ;}
#endif
base.OnEnable();
D.assert(_wrapper == null);
_configurations = new Configurations();

66
com.unity.uiwidgets/Runtime/engine2/UIWidgetsPanelWrapper.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using AOT;
using Unity.UIWidgets.engine2;

using Unity.UIWidgets.ui;
using UnityEngine;
using Path = Unity.UIWidgets.ui.Path;
namespace Unity.UIWidgets.engine2 {
#region Platform: Windows Specific Functionalities

#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
public partial class UIWidgetsPanelWrapper {
Texture _renderTexture;
public Texture renderTexture {
get { return _renderTexture; }
}

#endregion
#region Platform: Android Runtime Specific Functionalities
#if (!UNITY_EDITOR && UNITY_ANDROID )
public partial class UIWidgetsPanelWrapper {
RenderTexture _renderTexture;
public RenderTexture renderTexture {
get { return _renderTexture; }
}
void _createRenderTexture(int width, int height, float devicePixelRatio) {
D.assert(_renderTexture == null);
var desc = new RenderTextureDescriptor(
width, height, RenderTextureFormat.ARGB32, 0) {
useMipMap = false,
autoGenerateMips = false,
};
_renderTexture = new RenderTexture(desc) {hideFlags = HideFlags.HideAndDontSave};
_renderTexture.Create();
_width = width;
_height = height;
this.devicePixelRatio = devicePixelRatio;
}
void _destroyRenderTexture() {
D.assert(_renderTexture != null);
ObjectUtils.SafeDestroy(_renderTexture);
_renderTexture = null;
}
void _enableUIWidgetsPanel(string font_settings) {
UIWidgetsPanel_onEnable(_ptr, _renderTexture.GetNativeTexturePtr(),
_width, _height, devicePixelRatio, Application.temporaryCachePath, font_settings);
}
void _resizeUIWidgetsPanel() {
UIWidgetsPanel_onRenderTexture(_ptr,
_renderTexture.GetNativeTexturePtr(),
_width, _height, devicePixelRatio);
}
void _disableUIWidgetsPanel() {
_renderTexture = null;
}
[DllImport(NativeBindings.dllName)]
static extern void UIWidgetsPanel_onEnable(IntPtr ptr,
IntPtr nativeTexturePtr, int width, int height, float dpi, string streamingAssetsPath,
string font_settings);
[DllImport(NativeBindings.dllName)]
static extern void UIWidgetsPanel_onRenderTexture(
IntPtr ptr, IntPtr nativeTexturePtr, int width, int height, float dpi);
}
#endif
#endregion
#region Window Common Properties and Functions

fontsetting.Add("fonts", _configurations.fontsToObject());
_enableUIWidgetsPanel(JSONMessageCodec.instance.toJson(message: fontsetting));
NativeConsole.OnEnable();
}
public void _entryPoint() {

1
com.unity.uiwidgets/Runtime/foundation/debug.cs


throw new AssertionError(message != null ? message() : "");
}
}
[Conditional("UNITY_ASSERTIONS")]
public static void assert(bool result, Func<string> message = null) {
if ( enableDebug && !result ) {

1
com.unity.uiwidgets/Runtime/material/material_state.cs


using System.Collections.Generic;
using Unity.UIWidgets.material;
using Unity.UIWidgets.ui;
using UnityEditor.VersionControl;
namespace Unity.UIWidgets.material {
public enum MaterialState {

1
com.unity.uiwidgets/Runtime/rendering/debug_overflow_indicator.cs


using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEditor.PackageManager;
using UnityEngine;
using Color = Unity.UIWidgets.ui.Color;
using Gradient = Unity.UIWidgets.ui.Gradient;

278
engine/Build.bee.cs


android
}
static class BuildUtils {
public static bool IsHostWindows() {
static class BuildUtils
{
public static bool IsHostWindows()
{
public static bool IsHostMac() {
public static bool IsHostMac()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
}
}

class Build
{
//bee.exe win
static void DeployWindows()
static void DeployWindows()
{
var libUIWidgets = SetupLibUIWidgets(UIWidgetsBuildTargetPlatform.windows, out var dependencies);

Backend.Current.AddAliasDependency("ProjectFiles", sln.Setup());
Backend.Current.AddAliasDependency("win", deployed.Path);
foreach(var dep in dependencies) {
foreach (var dep in dependencies)
{
static void DeployAndroid()
{
var libUIWidgets = SetupLibUIWidgets(UIWidgetsBuildTargetPlatform.android, out var dependencies);
var androidProject = AndroidNativeProgramExtensions.DynamicLinkerSettingsForAndroid(libUIWidgets);
foreach (var dep in dependencies)
{
Backend.Current.AddAliasDependency("android", dep);
}
}
static void DeployMac()
{
var libUIWidgets = SetupLibUIWidgets(UIWidgetsBuildTargetPlatform.mac, out var dependencies);

var xcodeProject = new XCodeProjectFile(nativePrograms, new NPath("libUIWidgetsMac.xcodeproj/project.pbxproj"));
Backend.Current.AddAliasDependency("mac", new NPath("libUIWidgetsMac.xcodeproj/project.pbxproj"));
foreach(var dep in dependencies) {
foreach (var dep in dependencies)
{
Backend.Current.AddAliasDependency("mac", dep);
}
}

{
flutterRoot = Environment.GetEnvironmentVariable("USERPROFILE") + "/engine/src";
}
skiaRoot = flutterRoot + "/third_party/skia";
//available target platforms of Windows

else if (BuildUtils.IsHostMac())
{
DeployMac();
DeployAndroid();
}
}

"src/shell/platform/unity/gfx_worker_task_runner.cc",
"src/shell/platform/unity/gfx_worker_task_runner.h",
"src/shell/platform/unity/uiwidgets_system.h",
"src/shell/platform/unity/unity_console.cc",
"src/shell/platform/unity/unity_console.h",

"src/shell/platform/unity/darwin/macos/unity_surface_manager.h",
};
var androidSource = new NPath[]
{
"src/shell/platform/unity/android_unpack_streaming_asset.cc",
"src/shell/platform/unity/android_unpack_streaming_asset.h",
"src/shell/platform/unity/android/unity_surface_manager.cc",
"src/shell/platform/unity/android/uiwidgets_system.cc",
"src/shell/platform/unity/android/android_task_runner.cc",
"src/shell/platform/unity/android/uiwidgets_panel.cc",
};
np.Sources.Add(c => IsAndroid(c), androidSource);
np.Libraries.Add(c => IsWindows(c), new BagOfObjectFilesLibrary(
new NPath[]{

np.CompilerSettings().Add(c => IsMac(c), c => c.WithCustomFlags(new []{"-Wno-c++11-narrowing"}));
np.CompilerSettings().Add(c => IsMac(c), c => c.WithCustomFlags(new[] { "-Wno-c++11-narrowing" }));
np.Defines.Add(c => IsAndroid(c), new[] {
"USE_OPENSSL=1",
"USE_OPENSSL_CERTS=1",
"ANDROID",
"HAVE_SYS_UIO_H",
"__STDC_CONSTANT_MACROS",
"__STDC_FORMAT_MACROS",
// "_FORTIFY_SOURCE=2",
"__compiler_offsetof=__builtin_offsetof",
"nan=__builtin_nan",
"__GNU_SOURCE=1",
"_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
"_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
"_DEBUG",
"U_USING_ICU_NAMESPACE=0",
"U_ENABLE_DYLOAD=0",
"USE_CHROMIUM_ICU=1",
"U_STATIC_IMPLEMENTATION",
"ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE",
"UCHAR_TYPE=uint16_t",
"FLUTTER_RUNTIME_MODE_DEBUG=1",
"FLUTTER_RUNTIME_MODE_PROFILE=2",
"FLUTTER_RUNTIME_MODE_RELEASE=3",
"FLUTTER_RUNTIME_MODE_JIT_RELEASE=4",
"FLUTTER_RUNTIME_MODE=1",
"FLUTTER_JIT_RUNTIME=1",
// confige for rapidjson
"UIWIDGETS_FORCE_ALIGNAS_8=\"1\"",
"RAPIDJSON_HAS_STDSTRING",
"RAPIDJSON_HAS_CXX11_RANGE_FOR",
"RAPIDJSON_HAS_CXX11_RVALUE_REFS",
"RAPIDJSON_HAS_CXX11_TYPETRAITS",
"RAPIDJSON_HAS_CXX11_NOEXCEPT",
"SK_ENABLE_SPIRV_VALIDATION",
"SK_GAMMA_APPLY_TO_A8",
"SK_GAMMA_EXPONENT=1.4",
"SK_GAMMA_CONTRAST=0.0",
"SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1",
"GR_TEST_UTILS=1",
"SKIA_IMPLEMENTATION=1",
"SK_GL",
"SK_ENABLE_DUMP_GPU",
"SK_SUPPORT_PDF",
"SK_CODEC_DECODES_JPEG",
"SK_ENCODE_JPEG",
"SK_ENABLE_ANDROID_UTILS",
"SK_USE_LIBGIFCODEC",
"SK_HAS_HEIF_LIBRARY",
"SK_CODEC_DECODES_PNG",
"SK_ENCODE_PNG",
"SK_CODEC_DECODES_RAW",
"SK_ENABLE_SKSL_INTERPRETER",
"SK_CODEC_DECODES_WEBP",
"SK_ENCODE_WEBP",
"SK_XML",
//"UIWIDGETS_ENGINE_VERSION=\"0.0\"",
//"SKIA_VERSION=\"0.0\"",
"XML_STATIC",
});
np.CompilerSettings().Add(c => IsAndroid(c), c => c.WithCustomFlags(new[] {
"-MD",
"-MF",
"-I.",
"-Ithird_party",
"-Isrc",
"-I"+ flutterRoot,
"-I"+ flutterRoot+"/third_party/rapidjson/include",
"-I"+ skiaRoot,
"-I"+ skiaRoot + "/include/third_party/vulkan",
"-I"+ flutterRoot+"/flutter/third_party/txt/src",
"-I" + flutterRoot + "/third_party/harfbuzz/src",
"-I" + skiaRoot + "/third_party/externals/icu/source/common",
// "-Igen",
"-I"+ flutterRoot+"/third_party/libcxx/include",
"-I"+ flutterRoot+"/third_party/libcxxabi/include",
"-I"+ flutterRoot+"/third_party/icu/source/common",
"-I"+ flutterRoot+"/third_party/icu/source/i18n",
// ignore deprecated code
"-Wno-deprecated-declarations",
"-fno-strict-aliasing",
"-march=armv7-a",
"-mfloat-abi=softfp",
"-mtune=generic-armv7-a",
"-mthumb",
"-fPIC",
"-pipe",
"-fcolor-diagnostics",
"-ffunction-sections",
"-funwind-tables",
"-fno-short-enums",
"-nostdinc++",
"--target=arm-linux-androideabi",
"-mfpu=neon",
"-Wall",
"-Wextra",
"-Wendif-labels",
"-Werror",
"-Wno-missing-field-initializers",
"-Wno-unused-parameter",
"-Wno-unused-variable",
"-Wno-unused-command-line-argument",
"-Wno-unused-function",
// "-Wno-non-c-typedef-for-linkage",
"-isystem"+ flutterRoot+"/third_party/android_tools/ndk/sources/android/support/include",
"-isystem"+ flutterRoot +
"/third_party/android_tools/ndk/sysroot/usr/include/arm-linux-androideabi",
//"-D__ANDROID_API__=16",
// "-fvisibility=hidden",
"--sysroot="+ flutterRoot+"/third_party/android_tools/ndk/sysroot",
"-Wstring-conversion",
// supress new line error
// "-Wnewline-eof",
"-O0",
"-g2",
"-fvisibility-inlines-hidden",
"-std=c++17",
"-fno-rtti",
"-fno-exceptions",
"-nostdlib"
}));
np.IncludeDirectories.Add("third_party");
np.IncludeDirectories.Add("src");

np.LinkerSettings().Add(c => IsWindows(c), l => l.WithCustomFlags_workaround(new[] { "/DEBUG:FULL" }));
np.LinkerSettings().Add(c => IsAndroid(c), l => l.WithCustomFlags_workaround(new[] {
"-Wl,--fatal-warnings",
"-fPIC",
"-Wl,-z,noexecstack",
"-Wl,-z,now",
"-Wl,-z,relro",
"-Wl,-z,defs",
"--gcc-toolchain="+ flutterRoot +
"/third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64",
"-Wl,--no-undefined",
"-Wl,--exclude-libs,ALL",
"-fuse-ld=lld",
"-Wl,--icf=all",
"--target=arm-linux-androideabi",
"-nostdlib++",
"-Wl,--warn-shared-textrel",
"-nostdlib",
"--sysroot="+ flutterRoot+"/third_party/android_tools/ndk/platforms/android-16/arch-arm",
"-L"+ flutterRoot + "/third_party/android_tools/ndk/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a",
"-Wl,--build-id=sha1",
"-g",
"-Wl,-soname=libUIWidgets_d.so",
"-Wl,--whole-archive",
}));
var codegens = new[] { CodeGen.Debug };
dependencies = new List<NPath>();

var builtNP = np.SetupSpecificConfiguration(config, toolchain.DynamicLibraryFormat)
.DeployTo("build");
else if (platform == UIWidgetsBuildTargetPlatform.android)
{
var androidToolchain = ToolChain.Store.Android().r19().Armv7();
var validConfigurations = new List<NativeProgramConfiguration>();
foreach (var codegen in codegens)
{
var config = new NativeProgramConfiguration(codegen, androidToolchain, lump: true);
validConfigurations.Add(config);
var buildNP = np.SetupSpecificConfiguration(config, androidToolchain.DynamicLibraryFormat).DeployTo("build");
var deoployNp = buildNP.DeployTo("../Samples/UIWidgetsSamples_2019_4/Assets/Plugins/Android");
dependencies.Add(buildNP.Path);
dependencies.Add(deoployNp.Path);
}
np.ValidConfigurations = validConfigurations;
}
else if (platform == UIWidgetsBuildTargetPlatform.mac)
{
var toolchain = ToolChain.Store.Host();

dependencies.Add(buildNp.Path);
dependencies.Add(deployNp.Path);
}
}
return np;

"FLUTTER_JIT_RUNTIME=1",
});
np.Defines.Add(c => IsMac(c), new []
np.Defines.Add(c => IsMac(c), new[]
{
"USE_OPENSSL=1",
"__STDC_CONSTANT_MACROS",

np.IncludeDirectories.Add(flutterRoot);
var fmlLibPath = flutterRoot + "/out/host_debug_unopt";
np.Libraries.Add(c => IsWindows(c), c => {
np.Libraries.Add(c => IsWindows(c), c =>
{
return new PrecompiledLibrary[]
{
new StaticLibrary(fmlLibPath + "/obj/flutter/fml/fml_lib.lib"),

np.Libraries.Add(c => IsMac(c), c => {
np.Libraries.Add(c => IsMac(c), c =>
{
return new PrecompiledLibrary[]
{
new StaticLibrary(fmlLibPath + "/obj/flutter/fml/libfml_lib.a"),

SetupRadidJson(np);
// TODO: fix warning, there are some type mismatches
var ignoreWarnigs = new string[] { "4244", "4267", "5030", "4101", "4996", "4359", "4018", "4091", "4722", "4312", "4838", "4172", "4005", "4311", "4477" };
var ignoreWarnigs = new string[] { "4244", "4267", "5030", "4101", "4996", "4359", "4018", "4091", "4722", "4312", "4838", "4172", "4005", "4311", "4477" };
np.Defines.Add(c => IsMac(c), new []
np.Defines.Add(c => IsMac(c), new[]
{
//lib flutter
"USE_OPENSSL=1",

});
//lib txt
np.Defines.Add(c => IsMac(c), new[] {
np.Defines.Add(c => IsMac(c), new[] {
"SK_USING_THIRD_PARTY_ICU", "U_USING_ICU_NAMESPACE=0",
"U_ENABLE_DYLOAD=0", "USE_CHROMIUM_ICU=1", "U_STATIC_IMPLEMENTATION",
"ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC"

flutterRoot + "/third_party/icu/source/common",
flutterRoot + "/third_party/icu/source/i18n",
});
np.CompilerSettings().Add(c => IsWindows(c), c => c.WithCustomFlags(new [] {
np.CompilerSettings().Add(c => IsWindows(c), c => c.WithCustomFlags(new[] {
"-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING",
"-DUSE_OPENSSL=1",
"-D__STD_C",

};
});
np.SupportFiles.Add(c => IsWindows(c), new [] {
np.SupportFiles.Add(c => IsWindows(c), new[] {
new DeployableFile(windowsSkiaBuild + "/libEGL.dll"),
new DeployableFile(windowsSkiaBuild + "/libEGL.dll.pdb"),
new DeployableFile(windowsSkiaBuild + "/libGLESv2.dll"),

np.Libraries.Add(IsMac, c => {
np.Libraries.Add(IsMac, c =>
{
return new PrecompiledLibrary[]
{
new StaticLibrary(flutterRoot+"/out/host_debug_unopt/obj/flutter/third_party/txt/libtxt_lib.a"),

new SystemFramework("CoreVideo"),
};
});
np.Libraries.Add(IsAndroid, c =>
{
var basePath = skiaRoot + "/out/arm";
return new PrecompiledLibrary[]
{
// icudtl
new StaticLibrary("icudtl.o"),
new StaticLibrary(flutterRoot+"/third_party/android_tools/ndk/platforms/android-16/arch-arm/usr/lib/crtbegin_so.o"),
new StaticLibrary(flutterRoot+"/third_party/android_tools/ndk/platforms/android-16/arch-arm/usr/lib/crtend_so.o"),
new StaticLibrary(flutterRoot+"/out/android_debug_unopt/obj/flutter/third_party/txt/libtxt_lib.a"),
new SystemLibrary("android_support"),
new SystemLibrary("unwind"),
new SystemLibrary("gcc"),
new SystemLibrary("c"),
new SystemLibrary("dl"),
new SystemLibrary("m"),
new SystemLibrary("android"),
new SystemLibrary("EGL"),
new SystemLibrary("GLESv2"),
new SystemLibrary("log"),
};
});
}
static void SetupSkia(NativeProgram np)

};
});
np.Libraries.Add(IsMac, c => {
np.Libraries.Add(IsMac, c =>
{
var basePath = skiaRoot + "/out/Debug";
return new PrecompiledLibrary[]
{

};
});
np.SupportFiles.Add(c => IsWindows(c), new [] {
np.SupportFiles.Add(c => IsWindows(c), new[] {
new DeployableFile(basePath + "/libEGL.dll"),
new DeployableFile(basePath + "/libEGL.dll.pdb"),
new DeployableFile(basePath + "/libGLESv2.dll"),

}
static void SetupTxtDependency(NativeProgram np)

var ignoreWarnigs = new string[] { "4091", "4722", "4312", "4838", "4172", "4005", "4311", "4477" }; // todo comparing the list with engine
txtLib.CompilerSettings().Add(s => s.WithWarningPolicies(ignoreWarnigs.Select((code) => new WarningAndPolicy(code, WarningPolicy.Silent)).ToArray()));
txtLib.CompilerSettings().Add(c => IsMac(c), c => c.WithCppLanguageVersion(CppLanguageVersion.Cpp17));
txtLib.CompilerSettings().Add(c => IsMac(c), c => c.WithCustomFlags(new []{"-Wno-c++11-narrowing"}));
txtLib.CompilerSettings().Add(c => IsMac(c), c => c.WithCustomFlags(new[] { "-Wno-c++11-narrowing" }));
txtLib.Defines.Add(c => c.CodeGen == CodeGen.Debug,
new[] { "_ITERATOR_DEBUG_LEVEL=2", "_HAS_ITERATOR_DEBUGGING=1", "_SECURE_SCL=1" });

63
engine/README.md


```
## How to Build (Android)
### Build flutter fml + skia + txt
1. Setting up the Engine development environment
Follow https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment
2. Checkout flutter-1.17-candidate.5
```
cd engine/src/flutter
git checkout flutter-1.17-candidate.5
gclient sync -D
```
Apply following to end of `flutter/third_party/txt/BUILD.gn`
```
diff --git a/third_party/txt/BUILD.gn b/third_party/txt/BUILD.gn
index 56b73a020..d42e88045 100644
--- a/third_party/txt/BUILD.gn
+++ b/third_party/txt/BUILD.gn
@@ -141,6 +141,7 @@ source_set("txt") {
"//third_party/harfbuzz",
"//third_party/icu",
"//third_party/skia",
+ "//third_party/skia/modules/skottie",
+ "//third_party/libcxx",
+ "//third_party/libcxxabi",
]
deps = [
@@ -339,3 +340,10 @@ executable("txt_benchmarks") {
deps += [ "//third_party/skia/modules/skparagraph" ]
}
}
+
+static_library("txt_lib") {
+ complete_static_lib = true
+ deps = [
+ ":txt",
+ ]
+}
```
remove `visibility = [ "../libcxx:*" ]` from `/build/secondary/third_party/libcxxabi/BUILD.gn`
cmd
```
cd $FLUTTER_ROOT
python ./flutter/tools/gn --unoptimized --android
ninja -C out/android_debug_unopt/ flutter/third_party/txt:txt_lib
```
If the compilation fails because "no available Mac SDK is found" (in flutter-1.17 the build tool will only try to find Mac 10.XX SDKs), please modify the file "/src/build/Mac/find_sdk.py" under flutter root by setting "sdks" as your current sdk, e.g., ['11.0'].
### build icu
```
cd <uiwidigets_dir>\engine
python $FLUTTER_ROOT/flutter/sky/tools/objcopy.py --objcopy $FLUTTER_ROOT/third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objcopy --input $FLUTTER_ROOT/third_party/icu/flutter/icudtl.dat --output icudtl.o --arch arm
```
### build uiwidgets
```
cd <uiwidigets_dir>\engine
mono bee.exe
```

16
engine/src/assets/directory_asset_bundle.cc


#include "flutter/fml/file.h"
#include "flutter/fml/mapping.h"
#if __ANDROID__
#include "shell/platform/unity/android_unpack_streaming_asset.h"
#endif
namespace uiwidgets {
DirectoryAssetBundle::DirectoryAssetBundle(fml::UniqueFD descriptor)

// |AssetResolver|
std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping(
const std::string& asset_name) const {
if (!is_valid_) {
const std::string &asset_name) const
{
if (!is_valid_)
{
#if __ANDROID__
AndroidUnpackStreamingAsset::Unpack(asset_name.c_str());
#endif
auto mapping = std::make_unique<fml::FileMapping>(fml::OpenFile(
descriptor_, asset_name.c_str(), false, fml::FilePermission::kRead));

return mapping;
}
} // namespace uiwidgets
} // namespace uiwidgets

1
engine/src/engine.cc


extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() {
uiwidgets::UIWidgetsSystem::GetInstancePtr()->UnBindUnityInterfaces();
}

16
engine/src/flow/raster_cache.cc


RasterCacheResult::RasterCacheResult(sk_sp<SkImage> image,
const SkRect& logical_rect)
: image_(std::move(image)), logical_rect_(logical_rect) {}
#if __ANDROID__
#define Math_abs(x) abs(x)
template<typename T>
T abs(T x) {
if (x < 0) {
return -x;
}
return x;
}
#else
#define Math_abs(x) std::abs(x)
#endif
void RasterCacheResult::draw(SkCanvas& canvas, const SkPaint* paint) const {
TRACE_EVENT0("uiwidgets", "RasterCacheResult::draw");

FML_DCHECK(
std::abs(bounds.size().width() - image_->dimensions().width()) <= 1 &&
std::abs(bounds.size().height() - image_->dimensions().height()) <= 1);
Math_abs(bounds.size().width() - image_->dimensions().width()) <= 1 &&
Math_abs(bounds.size().height() - image_->dimensions().height()) <= 1);
canvas.resetMatrix();
canvas.drawImage(image_, bounds.fLeft, bounds.fTop, paint);
}

11
engine/src/lib/ui/painting/skottie.cc


#include "skottie.h"
#include "lib/ui/ui_mono_state.h"
#if __ANDROID__
#include "shell/platform/unity/android_unpack_streaming_asset.h"
#endif
#if __ANDROID__
std::string pthstr = std::string(path);
int id = pthstr.find("assets/") + 7;
std::string file = pthstr.substr(id);
const char* fileOut = AndroidUnpackStreamingAsset::Unpack(file.c_str());
path = (char*)fileOut;
#endif
sk_sp<skottie::Animation> animation_ = skottie::Animation::MakeFromFile(path);
return fml::MakeRefCounted<Skottie>(animation_);
}

2
engine/src/lib/ui/text/paragraph.cc


}
UIWIDGETS_API(void) Paragraph_dispose(Paragraph* ptr) { ptr->Release(); }
} // namespace uiwidgets
} // namespace uiwidgets

5
engine/src/runtime/mono_api.cc


pthread_threadid_np(NULL, &tid);
return tid;
}
#elif __ANDROID__
uint64_t GetCurrentThreadId() {
return gettid();
}
namespace uiwidgets {
FML_THREAD_LOCAL fml::ThreadLocalUniquePtr<Mono_Isolate> tls_isolate;

2
engine/src/shell/common/lists.cc


#pragma once
#include "lists.h"
namespace uiwidgets {

2
engine/src/shell/gpu/gpu_surface_gl_delegate.cc


#pragma once
#include "gpu_surface_gl_delegate.h"
#include "include/gpu/gl/GrGLAssembleInterface.h"

2
engine/src/shell/platform/embedder/embedder_render_target.cc


#pragma once
#include "embedder_render_target.h"
#include "flutter/fml/logging.h"

2
engine/src/shell/platform/embedder/embedder_surface_software.cc


#pragma once
#include "embedder_surface_software.h"
#include "flutter/fml/trace_event.h"

2
engine/src/shell/platform/unity/gfx_worker_task_runner.cc


void GfxWorkerTaskRunner::PostTask(UIWidgetsTask uiwidgets_task,
uint64_t uiwidgets_target_time_nanos) {
FML_DCHECK(uiwidgets_target_time_nanos <=
fml::TimePoint::Now().ToEpochDelta().ToNanoseconds());
(uint64_t)fml::TimePoint::Now().ToEpochDelta().ToNanoseconds());
UIWidgetsSystem::GetInstancePtr()->PostTaskToGfxWorker(
[&on_task_expired = on_task_expired_, uiwidgets_task]() -> void {

4
engine/src/shell/platform/unity/uiwidgets_system.h


#pragma once
#ifdef __APPLE__
#ifdef __ANDROID__
#include "shell/platform/unity/android/uiwidgets_system.h"
#elif __APPLE__
#include "shell/platform/unity/darwin/macos/uiwidgets_system.h"
#elif _WIN64
#include "shell/platform/unity/windows/uiwidgets_system.h"

45
com.unity.uiwidgets/Runtime/engine2/AndroidPlatformUtil.cs


#if !UNITY_EDITOR && UNITY_ANDROID
using UnityEngine;
using AOT;
using System;
using System.IO;
using System.Runtime.InteropServices;
using NativeBindings = Unity.UIWidgets.ui.NativeBindings;
namespace Unity.UIWidgets.engine2 {
public static class AndroidPlatformUtil {
[DllImport(NativeBindings.dllName)]
internal static extern void InitUnpackFile(UnpackFileCallback unpack);
internal delegate string UnpackFileCallback(string file);
[MonoPInvokeCallback(typeof(UnpackFileCallback))]
internal static string unpackFile(string file) {
var dir = Application.temporaryCachePath + "/";
if (!File.Exists(dir + file)) {
WWW unpackerWWW = new WWW("jar:file://" + Application.dataPath + "!/assets/" + file);
while (!unpackerWWW.isDone) {
} // This will block in the webplayer.
if (!string.IsNullOrEmpty(unpackerWWW.error)) {
Debug.Log("Error unpacking 'jar:file://" + Application.dataPath + "!/assets/" + file +
"'");
dir = "";
return dir + file;
}
File.WriteAllBytes(dir + file, unpackerWWW.bytes); // 64MB limit on File.WriteAllBytes.
}
return dir + file;
}
[DllImport(NativeBindings.dllName)]
static extern System.IntPtr GetUnityContextEventFunc();
public static void Init() {
InitUnpackFile(unpackFile);
GL.IssuePluginEvent(GetUnityContextEventFunc(), 1);
}
}
}
#endif

3
com.unity.uiwidgets/Runtime/engine2/AndroidPlatformUtil.cs.meta


fileFormatVersion: 2
guid: 76a442e0d2934484b6b95ed3b22889f2
timeCreated: 1616467811

17
engine/src/shell/platform/unity/android_unpack_streaming_asset.cc


#include "android_unpack_streaming_asset.h"
#include <stdarg.h>
namespace uiwidgets {
const char* AndroidUnpackStreamingAsset::Unpack(const char* file) {
return _unpack(file);
}
UnpackFileCallback AndroidUnpackStreamingAsset::_unpack;
UIWIDGETS_API(void)
InitUnpackFile(UnpackFileCallback _unpack) {
AndroidUnpackStreamingAsset::_unpack = _unpack;
}
}

16
engine/src/shell/platform/unity/android_unpack_streaming_asset.h


#pragma once
#include "runtime/mono_api.h"
namespace uiwidgets {
typedef const char* (*UnpackFileCallback)(const char* file);
class AndroidUnpackStreamingAsset{
public:
static UnpackFileCallback _unpack;
static const char* Unpack(const char* file);
};
} // namespace uiwidgets

94
engine/src/shell/platform/unity/android/uiwidgets_system.cc


#include "uiwidgets_system.h"
#include <algorithm>
#include <chrono>
#include "uiwidgets_panel.h"
namespace uiwidgets {
UIWidgetsSystem g_uiwidgets_system;
UIWidgetsSystem::UIWidgetsSystem() = default;
UIWidgetsSystem::~UIWidgetsSystem() = default;
void UIWidgetsSystem::RegisterPanel(UIWidgetsPanel* panel) {
uiwidgets_panels_.insert(panel);
}
void UIWidgetsSystem::UnregisterPanel(UIWidgetsPanel* panel) {
uiwidgets_panels_.erase(panel);
}
void UIWidgetsSystem::Wait(std::chrono::nanoseconds max_duration) {
Update();
std::chrono::nanoseconds wait_duration =
std::max(std::chrono::nanoseconds(0),
next_uiwidgets_event_time_ - TimePoint::clock::now());
wait_duration = std::min(max_duration, wait_duration);
//TODO: find a proper api similar to MsgWaitForMultipleObjects on Windows
// which will notify os to wait for the given period of time
}
void UIWidgetsSystem::Update() {
TimePoint next_event_time = TimePoint::max();
for (auto* uiwidgets_panel : uiwidgets_panels_) {
std::chrono::nanoseconds wait_duration = uiwidgets_panel->ProcessMessages();
if (wait_duration != std::chrono::nanoseconds::max()) {
next_event_time =
std::min(next_event_time, TimePoint::clock::now() + wait_duration);
}
}
next_uiwidgets_event_time_ = next_event_time;
}
void UIWidgetsSystem::VSync() {
for (auto* uiwidgets_panel : uiwidgets_panels_) {
uiwidgets_panel->ProcessVSync();
}
}
void UIWidgetsSystem::WakeUp() {}
void UIWidgetsSystem::GfxWorkerCallback(int eventId, void* data) {
const fml::closure task(std::move(gfx_worker_tasks_[eventId]));
gfx_worker_tasks_.erase(eventId);
task();
}
void UIWidgetsSystem::PostTaskToGfxWorker(const fml::closure& task) {
last_task_id_++;
gfx_worker_tasks_[last_task_id_] = task;
unity_uiwidgets_->IssuePluginEventAndData(&_GfxWorkerCallback, last_task_id_,
nullptr);
}
void UIWidgetsSystem::BindUnityInterfaces(IUnityInterfaces* unity_interfaces) {
unity_interfaces_ = unity_interfaces;
unity_uiwidgets_ = unity_interfaces_->Get<UnityUIWidgets::IUnityUIWidgets>();
unity_uiwidgets_->SetUpdateCallback(_Update);
unity_uiwidgets_->SetVSyncCallback(_VSync);
unity_uiwidgets_->SetWaitCallback(_Wait);
unity_uiwidgets_->SetWakeUpCallback(_WakeUp);
}
void UIWidgetsSystem::UnBindUnityInterfaces() {
unity_uiwidgets_->SetUpdateCallback(nullptr);
unity_uiwidgets_->SetVSyncCallback(nullptr);
unity_uiwidgets_->SetWaitCallback(nullptr);
unity_uiwidgets_->SetWakeUpCallback(nullptr);
unity_uiwidgets_ = nullptr;
unity_interfaces_ = nullptr;
}
UIWidgetsSystem* UIWidgetsSystem::GetInstancePtr() {
return &g_uiwidgets_system;
}
} // namespace uiwidgets

86
engine/src/shell/platform/unity/android/uiwidgets_system.h


#pragma once
#include <flutter/fml/closure.h>
#include <chrono>
#include <cstdarg>
#include <set>
#include <unordered_map>
#include "Unity/IUnityInterface.h"
#include "Unity/IUnityUIWidgets.h"
#include "flutter/fml/macros.h"
#include "runtime/mono_api.h"
#include <GLES2/gl2.h>
#include <EGL/egl.h>
namespace uiwidgets {
using TimePoint = std::chrono::steady_clock::time_point;
class UIWidgetsPanel;
class UIWidgetsSystem {
public:
UIWidgetsSystem();
~UIWidgetsSystem();
void RegisterPanel(UIWidgetsPanel* panel);
void UnregisterPanel(UIWidgetsPanel* panel);
void PostTaskToGfxWorker(const fml::closure& task);
void printf_console(const char* log, ...) {
va_list vl;
va_start(vl, log);
// TODO: error in __android_log_vprint -> vsnprintf -> __vfprintf -> strlen_a
// unity_uiwidgets_->printf_consolev(log, vl);
va_end(vl);
}
void BindUnityInterfaces(IUnityInterfaces* unity_interfaces);
void UnBindUnityInterfaces();
IUnityInterfaces* GetUnityInterfaces() { return unity_interfaces_; }
static UIWidgetsSystem* GetInstancePtr();
FML_DISALLOW_COPY_AND_ASSIGN(UIWidgetsSystem);
private:
UIWIDGETS_CALLBACK(void) _Update() {
GetInstancePtr()->Update();
}
UIWIDGETS_CALLBACK(void) _Wait(long max_duration) {
GetInstancePtr()->Wait(std::chrono::nanoseconds(max_duration));
}
UIWIDGETS_CALLBACK(void) _VSync() { GetInstancePtr()->VSync(); }
UIWIDGETS_CALLBACK(void) _WakeUp() { GetInstancePtr()->WakeUp(); }
UIWIDGETS_CALLBACK(void) _GfxWorkerCallback(int eventId, void* data) {
auto context = eglGetCurrentContext();
auto display = eglGetCurrentDisplay();
auto draw = eglGetCurrentSurface(EGL_DRAW);
auto read = eglGetCurrentSurface(EGL_READ);
GetInstancePtr()->GfxWorkerCallback(eventId, data);
eglMakeCurrent(display, draw, read, context);
}
void Update();
void Wait(std::chrono::nanoseconds max_duration);
void VSync();
void WakeUp();
void GfxWorkerCallback(int eventId, void* data);
IUnityInterfaces* unity_interfaces_ = nullptr;
UnityUIWidgets::IUnityUIWidgets* unity_uiwidgets_ = nullptr;
std::unordered_map<int, fml::closure> gfx_worker_tasks_;
int last_task_id_ = 0;
TimePoint next_uiwidgets_event_time_ = TimePoint::clock::now();
std::set<UIWidgetsPanel*> uiwidgets_panels_;
};
} // namespace uiwidgets

586
engine/src/shell/platform/unity/android/uiwidgets_panel.cc


#include "uiwidgets_panel.h"
#include <flutter/fml/synchronization/waitable_event.h>
#include <fstream>
#include <iostream>
#include "lib/ui/window/viewport_metrics.h"
#include "runtime/mono_api.h"
#include "shell/common/switches.h"
#include "shell/platform/embedder/embedder_engine.h"
#include "uiwidgets_system.h"
#include "third_party/Unity/IUnityGraphics.h"
namespace uiwidgets
{
fml::RefPtr<UIWidgetsPanel> UIWidgetsPanel::Create(
Mono_Handle handle, UIWidgetsWindowType window_type, EntrypointCallback entrypoint_callback)
{
return fml::MakeRefCounted<UIWidgetsPanel>(handle, window_type, entrypoint_callback);
}
UIWidgetsPanel::UIWidgetsPanel(Mono_Handle handle,
UIWidgetsWindowType window_type,
EntrypointCallback entrypoint_callback)
: handle_(handle), window_type_(window_type), entrypoint_callback_(entrypoint_callback) {}
UIWidgetsPanel::~UIWidgetsPanel() = default;
bool UIWidgetsPanel::NeedUpdateByPlayerLoop()
{
return window_type_ == GameObjectPanel;
}
bool UIWidgetsPanel::NeedUpdateByEditorLoop()
{
return window_type_ == EditorWindowPanel;
}
void UIWidgetsPanel::OnEnable(void *native_texture_ptr, size_t width,
size_t height, float device_pixel_ratio,
const char *streaming_assets_path,
const char *settings)
{
surface_manager_ = std::make_unique<UnitySurfaceManager>(
UIWidgetsSystem::GetInstancePtr()->GetUnityInterfaces());
FML_DCHECK(fbo_ == 0);
surface_manager_->MakeCurrent(EGL_NO_DISPLAY);
fbo_ = surface_manager_->CreateRenderSurface(native_texture_ptr);
surface_manager_->ClearCurrent();
fml::AutoResetWaitableEvent latch;
std::thread::id gfx_worker_thread_id;
UIWidgetsSystem::GetInstancePtr()->PostTaskToGfxWorker(
[&latch, &gfx_worker_thread_id]() -> void {
gfx_worker_thread_id = std::this_thread::get_id();
latch.Signal();
});
latch.Wait();
gfx_worker_task_runner_ = std::make_unique<GfxWorkerTaskRunner>(
gfx_worker_thread_id, [this](const auto *task) {
if (UIWidgetsEngineRunTask(engine_, task) != kSuccess)
{
std::cerr << "Could not post an gfx worker task." << std::endl;
}
});
UIWidgetsTaskRunnerDescription render_task_runner = {};
render_task_runner.struct_size = sizeof(UIWidgetsTaskRunnerDescription);
render_task_runner.identifier = 1;
render_task_runner.user_data = gfx_worker_task_runner_.get();
render_task_runner.runs_task_on_current_thread_callback =
[](void *user_data) -> bool {
return static_cast<GfxWorkerTaskRunner *>(user_data)
->RunsTasksOnCurrentThread();
};
render_task_runner.post_task_callback = [](UIWidgetsTask task,
uint64_t target_time_nanos,
void *user_data) -> void {
static_cast<GfxWorkerTaskRunner *>(user_data)->PostTask(task,
target_time_nanos);
};
UIWidgetsRendererConfig config = {};
config.type = kOpenGL;
config.open_gl.struct_size = sizeof(config.open_gl);
config.open_gl.clear_current = [](void *user_data) -> bool {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
return panel->surface_manager_->ClearCurrent();
};
config.open_gl.make_current = [](void *user_data) -> bool {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
return panel->surface_manager_->MakeCurrent(EGL_NO_DISPLAY);
};
config.open_gl.make_resource_current = [](void *user_data) -> bool {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
return panel->surface_manager_->MakeResourceCurrent();
};
config.open_gl.fbo_callback = [](void *user_data) -> uint32_t {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
return panel->fbo_;
};
config.open_gl.present = [](void *user_data) -> bool { return true; };
config.open_gl.gl_proc_resolver = [](void *user_data,
const char *what) -> void * {
return reinterpret_cast<void *>(eglGetProcAddress(what));
};
config.open_gl.fbo_reset_after_present = true;
task_runner_ = std::make_unique<CocoaTaskRunner>(
gettid(), [this](const auto *task) {
if (UIWidgetsEngineRunTask(engine_, task) != kSuccess)
{
std::cerr << "Could not post an engine task." << std::endl;
}
});
UIWidgetsTaskRunnerDescription ui_task_runner = {};
ui_task_runner.struct_size = sizeof(UIWidgetsTaskRunnerDescription);
ui_task_runner.identifier = 2;
ui_task_runner.user_data = task_runner_.get();
ui_task_runner.runs_task_on_current_thread_callback =
[](void *user_data) -> bool {
return static_cast<CocoaTaskRunner *>(user_data)->RunsTasksOnCurrentThread();
};
ui_task_runner.post_task_callback = [](UIWidgetsTask task,
uint64_t target_time_nanos,
void *user_data) -> void {
static_cast<CocoaTaskRunner *>(user_data)->PostTask(task, target_time_nanos);
};
UIWidgetsCustomTaskRunners custom_task_runners = {};
custom_task_runners.struct_size = sizeof(UIWidgetsCustomTaskRunners);
custom_task_runners.platform_task_runner = &ui_task_runner;
custom_task_runners.ui_task_runner = &ui_task_runner;
custom_task_runners.render_task_runner = &render_task_runner;
UIWidgetsProjectArgs args = {};
args.struct_size = sizeof(UIWidgetsProjectArgs);
args.assets_path = streaming_assets_path;
args.font_asset = settings;
args.icu_mapper = GetICUStaticMapping;
// // Used for IOS build
// // std::string icu_symbol_prefix = "_binary_icudtl_dat_start";
// // std::string native_lib_path =
// // "pathtodll/Plugins/x86_64/libUIWidgets_d.dll"; args.icu_mapper =
// // [icu_symbol_prefix, native_lib_path] {
// // return GetSymbolMapping(icu_symbol_prefix, native_lib_path);
// // };
args.command_line_argc = 0;
args.command_line_argv = nullptr;
args.platform_message_callback =
[](const UIWidgetsPlatformMessage *engine_message,
void *user_data) -> void {};
args.custom_task_runners = &custom_task_runners;
args.task_observer_add = [](intptr_t key, void *callback,
void *user_data) -> void {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
panel->task_runner_->AddTaskObserver(key,
*static_cast<fml::closure *>(callback));
};
args.task_observer_remove = [](intptr_t key, void *user_data) -> void {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
panel->task_runner_->RemoveTaskObserver(key);
};
args.custom_mono_entrypoint = [](void *user_data) -> void {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
panel->MonoEntrypoint();
};
args.vsync_callback = [](void *user_data, intptr_t baton) -> void {
auto *panel = static_cast<UIWidgetsPanel *>(user_data);
panel->VSyncCallback(baton);
};
args.initial_window_metrics.width = width;
args.initial_window_metrics.height = height;
args.initial_window_metrics.pixel_ratio = device_pixel_ratio;
UIWidgetsEngine engine = nullptr;
auto result = UIWidgetsEngineInitialize(&config, &args, this, &engine);
if (result != kSuccess || engine == nullptr)
{
std::cerr << "Failed to start UIWidgets engine: error " << result
<< std::endl;
return;
}
engine_ = engine;
UIWidgetsEngineRunInitialized(engine);
UIWidgetsSystem::GetInstancePtr()->RegisterPanel(this);
process_events_ = true;
}
void UIWidgetsPanel::MonoEntrypoint() { entrypoint_callback_(handle_); }
void UIWidgetsPanel::OnDisable()
{
// drain pending messages
ProcessMessages();
// drain pending vsync batons
ProcessVSync();
process_events_ = false;
UIWidgetsSystem::GetInstancePtr()->UnregisterPanel(this);
if (engine_)
{
UIWidgetsEngineShutdown(engine_);
engine_ = nullptr;
}
gfx_worker_task_runner_ = nullptr;
task_runner_ = nullptr;
if (fbo_)
{
surface_manager_->MakeCurrent(EGL_NO_DISPLAY);
surface_manager_->DestroyRenderSurface();
fbo_ = 0;
surface_manager_->ClearCurrent();
}
surface_manager_ = nullptr;
}
void UIWidgetsPanel::OnRenderTexture(void *native_texture_ptr, size_t width,
size_t height, float device_pixel_ratio)
{
reinterpret_cast<EmbedderEngine *>(engine_)->PostRenderThreadTask(
[this, native_texture_ptr]() -> void {
surface_manager_->MakeCurrent(EGL_NO_DISPLAY);
if (fbo_)
{
surface_manager_->DestroyRenderSurface();
fbo_ = 0;
}
fbo_ = surface_manager_->CreateRenderSurface(native_texture_ptr);
surface_manager_->ClearCurrent();
});
ViewportMetrics metrics;
metrics.physical_width = static_cast<float>(width);
metrics.physical_height = static_cast<float>(height);
metrics.device_pixel_ratio = device_pixel_ratio;
reinterpret_cast<EmbedderEngine *>(engine_)->SetViewportMetrics(metrics);
}
int UIWidgetsPanel::RegisterTexture(void *native_texture_ptr)
{
std::cerr << "registering external texture is not implemented for android" << std::endl;
int texture_identifier = 0;
// texture_identifier++;
// auto* engine = reinterpret_cast<EmbedderEngine*>(engine_);
// engine->GetShell().GetPlatformView()->RegisterTexture(
// std::make_unique<UnityExternalTextureGL>(
// texture_identifier, native_texture_ptr, surface_manager_.get()));
return texture_identifier;
}
void UIWidgetsPanel::UnregisterTexture(int texture_id)
{
std::cerr << "registering external texture is not implemented for android" << std::endl;
auto *engine = reinterpret_cast<EmbedderEngine *>(engine_);
engine->GetShell().GetPlatformView()->UnregisterTexture(texture_id);
}
std::chrono::nanoseconds UIWidgetsPanel::ProcessMessages()
{
return std::chrono::nanoseconds(task_runner_->ProcessTasks().count());
}
void UIWidgetsPanel::ProcessVSync()
{
std::vector<intptr_t> batons;
vsync_batons_.swap(batons);
for (intptr_t baton : batons)
{
reinterpret_cast<EmbedderEngine *>(engine_)->OnVsyncEvent(
baton, fml::TimePoint::Now(),
fml::TimePoint::Now() +
fml::TimeDelta::FromNanoseconds(1000000000 / 60));
}
}
void UIWidgetsPanel::VSyncCallback(intptr_t baton)
{
vsync_batons_.push_back(baton);
}
void UIWidgetsPanel::SetEventPhaseFromCursorButtonState(
UIWidgetsPointerEvent *event_data)
{
MouseState state = GetMouseState();
event_data->phase = state.buttons == 0
? state.state_is_down ? UIWidgetsPointerPhase::kUp
: UIWidgetsPointerPhase::kHover
: state.state_is_down ? UIWidgetsPointerPhase::kMove
: UIWidgetsPointerPhase::kDown;
}
void UIWidgetsPanel::SendMouseMove(float x, float y)
{
UIWidgetsPointerEvent event = {};
event.x = x;
event.y = y;
SetEventPhaseFromCursorButtonState(&event);
SendPointerEventWithData(event);
}
void UIWidgetsPanel::SendMouseDown(float x, float y)
{
UIWidgetsPointerEvent event = {};
SetEventPhaseFromCursorButtonState(&event);
event.x = x;
event.y = y;
SendPointerEventWithData(event);
SetMouseStateDown(true);
}
void UIWidgetsPanel::SendMouseUp(float x, float y)
{
UIWidgetsPointerEvent event = {};
SetEventPhaseFromCursorButtonState(&event);
event.x = x;
event.y = y;
SendPointerEventWithData(event);
if (event.phase == UIWidgetsPointerPhase::kUp)
{
SetMouseStateDown(false);
}
}
void UIWidgetsPanel::SendMouseLeave()
{
UIWidgetsPointerEvent event = {};
event.phase = UIWidgetsPointerPhase::kRemove;
SendPointerEventWithData(event);
}
void UIWidgetsPanel::SendPointerEventWithData(
const UIWidgetsPointerEvent &event_data)
{
MouseState mouse_state = GetMouseState();
// If sending anything other than an add, and the pointer isn't already added,
// synthesize an add to satisfy Flutter's expectations about events.
if (!mouse_state.state_is_added &&
event_data.phase != UIWidgetsPointerPhase::kAdd)
{
UIWidgetsPointerEvent event = {};
event.phase = UIWidgetsPointerPhase::kAdd;
event.x = event_data.x;
event.y = event_data.y;
event.buttons = 0;
SendPointerEventWithData(event);
}
// Don't double-add (e.g., if events are delivered out of order, so an add has
// already been synthesized).
if (mouse_state.state_is_added &&
event_data.phase == UIWidgetsPointerPhase::kAdd)
{
return;
}
UIWidgetsPointerEvent event = event_data;
event.device_kind = kUIWidgetsPointerDeviceKindMouse;
event.buttons = mouse_state.buttons;
// Set metadata that's always the same regardless of the event.
event.struct_size = sizeof(event);
event.timestamp =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count();
UIWidgetsEngineSendPointerEvent(engine_, &event, 1);
if (event_data.phase == UIWidgetsPointerPhase::kAdd)
{
SetMouseStateAdded(true);
}
else if (event_data.phase == UIWidgetsPointerPhase::kRemove)
{
SetMouseStateAdded(false);
ResetMouseState();
}
}
void UIWidgetsPanel::OnKeyDown(int keyCode, bool isKeyDown)
{
if (process_events_)
{
UIWidgetsPointerEvent event = {};
event.phase = isKeyDown ? UIWidgetsPointerPhase::kMouseDown : UIWidgetsPointerPhase::kMouseUp;
event.device_kind =
UIWidgetsPointerDeviceKind::kUIWidgetsPointerDeviceKindKeyboard;
event.buttons = keyCode;
event.struct_size = sizeof(event);
event.timestamp =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch())
.count();
UIWidgetsEngineSendPointerEvent(engine_, &event, 1);
}
}
void UIWidgetsPanel::OnMouseMove(float x, float y)
{
if (process_events_)
{
SendMouseMove(x, y);
}
}
static uint64_t ConvertToUIWidgetsButton(int button)
{
switch (button)
{
case -1:
return kUIWidgetsPointerButtonMousePrimary;
case -2:
return kUIWidgetsPointerButtonMouseSecondary;
case -3:
return kUIWidgetsPointerButtonMouseMiddle;
}
std::cerr << "Mouse button not recognized: " << button << std::endl;
return 0;
}
void UIWidgetsPanel::OnMouseDown(float x, float y, int button)
{
if (process_events_)
{
uint64_t uiwidgets_button = ConvertToUIWidgetsButton(button);
if (uiwidgets_button != 0)
{
uint64_t mouse_buttons = GetMouseState().buttons | uiwidgets_button;
SetMouseButtons(mouse_buttons);
SendMouseDown(x, y);
}
}
}
void UIWidgetsPanel::OnMouseUp(float x, float y, int button)
{
if (process_events_)
{
uint64_t uiwidgets_button = ConvertToUIWidgetsButton(button);
if (uiwidgets_button != 0)
{
uint64_t mouse_buttons = GetMouseState().buttons & ~uiwidgets_button;
SetMouseButtons(mouse_buttons);
SendMouseUp(x, y);
}
}
}
void UIWidgetsPanel::OnMouseLeave()
{
if (process_events_)
{
SendMouseLeave();
}
}
UIWIDGETS_API(UIWidgetsPanel *)
UIWidgetsPanel_constructor(
Mono_Handle handle, int windowType,
UIWidgetsPanel::EntrypointCallback entrypoint_callback)
{
UIWidgetsWindowType window_type = static_cast<UIWidgetsWindowType>(windowType);
const auto panel = UIWidgetsPanel::Create(handle, window_type, entrypoint_callback);
panel->AddRef();
// entrypoint_callback(handle);
return panel.get();
}
UIWIDGETS_API(void)
UIWidgetsPanel_dispose(UIWidgetsPanel *panel)
{
panel->Release();
}
UIWIDGETS_API(void)
UIWidgetsPanel_onEnable(UIWidgetsPanel *panel, void *native_texture_ptr,
size_t width, size_t height, float device_pixel_ratio,
const char *streaming_assets_path,
const char *settings)
{
panel->OnEnable(native_texture_ptr, width, height, device_pixel_ratio,
streaming_assets_path, settings);
}
UIWIDGETS_API(void)
UIWidgetsPanel_onDisable(UIWidgetsPanel *panel)
{
panel->OnDisable();
}
UIWIDGETS_API(void)
UIWidgetsPanel_onRenderTexture(UIWidgetsPanel *panel, void *native_texture_ptr,
int width, int height, float dpi)
{
panel->OnRenderTexture(native_texture_ptr, width, height, dpi);
}
UIWIDGETS_API(int)
UIWidgetsPanel_registerTexture(UIWidgetsPanel *panel,
void *native_texture_ptr)
{
return panel->RegisterTexture(native_texture_ptr);
}
UIWIDGETS_API(void)
UIWidgetsPanel_unregisterTexture(UIWidgetsPanel *panel, int texture_id)
{
panel->UnregisterTexture(texture_id);
}
UIWIDGETS_API(void)
UIWidgetsPanel_onKey(UIWidgetsPanel *panel, int keyCode, bool isKeyDown)
{
panel->OnKeyDown(keyCode, isKeyDown);
}
UIWIDGETS_API(void)
UIWidgetsPanel_onMouseDown(UIWidgetsPanel *panel, float x, float y,
int button)
{
panel->OnMouseDown(x, y, button);
}
UIWIDGETS_API(void)
UIWidgetsPanel_onMouseUp(UIWidgetsPanel *panel, float x, float y, int button)
{
panel->OnMouseUp(x, y, button);
}
UIWIDGETS_API(void)
UIWidgetsPanel_onMouseMove(UIWidgetsPanel *panel, float x, float y)
{
panel->OnMouseMove(x, y);
}
UIWIDGETS_API(void)
UIWidgetsPanel_onMouseLeave(UIWidgetsPanel *panel) { panel->OnMouseLeave(); }
static void UNITY_INTERFACE_API OnGetUnityContextEvent(int eventID)
{
UnitySurfaceManager::GetUnityContext();
}
// --------------------------------------------------------------------------
// GetRenderEventFunc, an example function we export which is used to get a rendering event callback function.
UIWIDGETS_API(UnityRenderingEvent)
GetUnityContextEventFunc()
{
return OnGetUnityContextEvent;
}
} // namespace uiwidgets

160
engine/src/shell/platform/unity/android/unity_surface_manager.cc


#include "unity_surface_manager.h"
#include <flutter/fml/logging.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include "src/shell/common/shell_io_manager.h"
#include "src/shell/gpu/gpu_surface_delegate.h"
#include "src/shell/gpu/gpu_surface_gl_delegate.h"
namespace uiwidgets
{
static EGLDisplay egl_display_;
static EGLContext egl_unity_context_;
template <class T>
using EGLResult = std::pair<bool, T>;
UnitySurfaceManager::UnitySurfaceManager(IUnityInterfaces *unity_interfaces)
: egl_context_(EGL_NO_CONTEXT),
egl_resource_context_(EGL_NO_CONTEXT)
{
initialize_succeeded_ = Initialize(unity_interfaces);
}
UnitySurfaceManager::~UnitySurfaceManager() { CleanUp(); }
GLuint UnitySurfaceManager::CreateRenderSurface(void *native_texture_ptr)
{
GLint old_framebuffer_binding;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_framebuffer_binding);
glGenFramebuffers(1, &fbo_);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
GLuint gltex = (GLuint)(size_t)(native_texture_ptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gltex, 0);
FML_CHECK(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, old_framebuffer_binding);
return fbo_;
}
void UnitySurfaceManager::DestroyRenderSurface()
{
FML_DCHECK(fbo_ != 0);
glDeleteFramebuffers(1, &fbo_);
fbo_ = 0;
}
bool UnitySurfaceManager::ClearCurrent()
{
return eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT) == EGL_TRUE;
}
bool UnitySurfaceManager::MakeCurrent(const EGLSurface surface)
{
return eglMakeCurrent(egl_display_, surface, surface, egl_context_) ==
EGL_TRUE;
}
bool UnitySurfaceManager::MakeResourceCurrent()
{
return eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
egl_resource_context_) == EGL_TRUE;
}
static EGLResult<EGLConfig> ChooseEGLConfiguration(EGLDisplay display)
{
EGLint attributes[] = {
// clang-format off
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_NONE, // termination sentinel
// clang-format on
};
EGLint config_count = 0;
EGLConfig egl_config = nullptr;
if (eglChooseConfig(display, attributes, &egl_config, 1, &config_count) !=
EGL_TRUE)
{
return {false, nullptr};
}
bool success = config_count > 0 && egl_config != nullptr;
return {success, success ? egl_config : nullptr};
}
static EGLResult<EGLSurface> CreateContext(EGLDisplay display,
EGLConfig config,
EGLContext share = EGL_NO_CONTEXT)
{
EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLContext context = eglCreateContext(display, config, share, attributes);
return {context != EGL_NO_CONTEXT, context};
}
void UnitySurfaceManager::GetUnityContext()
{
if(egl_unity_context_ != nullptr){
return;
}
egl_display_ = eglGetCurrentDisplay();
egl_unity_context_ = eglGetCurrentContext();
FML_CHECK(egl_display_ != EGL_NO_DISPLAY)
<< "Renderer type is invalid";
}
bool UnitySurfaceManager::Initialize(IUnityInterfaces *unity_interfaces)
{
FML_CHECK(egl_display_ != EGL_NO_DISPLAY)
<< "Renderer type is invalid";
// Initialize the display connection.
FML_CHECK(eglInitialize(egl_display_, nullptr, nullptr) == EGL_TRUE)
<< "Renderer type is invalid";
auto valid_ = true;
bool success = false;
std::tie(success, egl_config_) = ChooseEGLConfiguration(egl_display_);
FML_CHECK(success) << "Could not choose an EGL configuration.";
std::tie(success, egl_context_) = CreateContext(egl_display_, egl_config_, egl_unity_context_);
std::tie(success, egl_resource_context_) = CreateContext(egl_display_, egl_config_, egl_context_);
return success;
}
void UnitySurfaceManager::CleanUp()
{
if (egl_display_ != EGL_NO_DISPLAY &&
egl_resource_context_ != EGL_NO_CONTEXT)
{
eglDestroyContext(egl_display_, egl_resource_context_);
egl_resource_context_ = EGL_NO_CONTEXT;
}
if (egl_display_ != EGL_NO_DISPLAY && egl_context_ != EGL_NO_CONTEXT)
{
eglDestroyContext(egl_display_, egl_context_);
egl_context_ = EGL_NO_CONTEXT;
}
}
} // namespace uiwidgets

63
engine/src/shell/platform/unity/android/unity_surface_manager.h


#pragma once
// OpenGL ES and EGL includes
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <cstdint>
#include "Unity/IUnityInterface.h"
#include "flutter/fml/macros.h"
#include <include/gpu/GrContext.h>
#include <src/gpu/gl/GrGLDefines.h>
#include "cassert"
#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/effects/SkPerlinNoiseShader.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "Unity/IUnityGraphics.h"
namespace uiwidgets
{
class UnitySurfaceManager
{
public:
static void GetUnityContext();
UnitySurfaceManager(IUnityInterfaces *unity_interfaces);
~UnitySurfaceManager();
GLuint CreateRenderSurface(void *native_texture_ptr);
void DestroyRenderSurface();
bool ClearCurrent();
bool MakeCurrent(const EGLSurface surface);
bool MakeResourceCurrent();
FML_DISALLOW_COPY_AND_ASSIGN(UnitySurfaceManager);
private:
bool Initialize(IUnityInterfaces *unity_interfaces);
void CleanUp();
EGLContext egl_context_;
EGLContext egl_resource_context_;
EGLConfig egl_config_;
bool initialize_succeeded_;
GLuint fbo_ = 0;
};
} // namespace uiwidgets

113
engine/src/shell/platform/unity/android/uiwidgets_panel.h


#pragma once
#include <flutter/fml/memory/ref_counted.h>
#include "shell/platform/unity/gfx_worker_task_runner.h"
#include "runtime/mono_api.h"
#include "unity_surface_manager.h"
#include "android_task_runner.h"
namespace uiwidgets {
enum UIWidgetsWindowType {
InvalidPanel = 0,
GameObjectPanel = 1,
EditorWindowPanel = 2
};
struct MouseState {
bool state_is_down = false;
bool state_is_added = false;
uint64_t buttons = 0;
};
class UIWidgetsPanel : public fml::RefCountedThreadSafe<UIWidgetsPanel> {
FML_FRIEND_MAKE_REF_COUNTED(UIWidgetsPanel);
public:
typedef void (*EntrypointCallback)(Mono_Handle handle);
static fml::RefPtr<UIWidgetsPanel> Create(
Mono_Handle handle, UIWidgetsWindowType window_type, EntrypointCallback entrypoint_callback);
~UIWidgetsPanel();
void OnEnable(void* native_texture_ptr, size_t width, size_t height,
float device_pixel_ratio, const char* streaming_assets_path,
const char* settings);
void MonoEntrypoint();
void OnDisable();
void OnRenderTexture(void* native_texture_ptr, size_t width, size_t height,
float dpi);
int RegisterTexture(void* native_texture_ptr);
void UnregisterTexture(int texture_id);
std::chrono::nanoseconds ProcessMessages();
void ProcessVSync();
void VSyncCallback(intptr_t baton);
void OnKeyDown(int keyCode, bool isKeyDown);
void OnMouseMove(float x, float y);
void OnMouseDown(float x, float y, int button);
void OnMouseUp(float x, float y, int button);
void OnMouseLeave();
bool NeedUpdateByPlayerLoop();
bool NeedUpdateByEditorLoop();
private:
UIWidgetsPanel(Mono_Handle handle, UIWidgetsWindowType window_type, EntrypointCallback entrypoint_callback);
MouseState GetMouseState() { return mouse_state_; }
void ResetMouseState() { mouse_state_ = MouseState(); }
void SetMouseStateDown(bool is_down) { mouse_state_.state_is_down = is_down; }
void SetMouseStateAdded(bool is_added) {
mouse_state_.state_is_added = is_added;
}
void SetMouseButtons(uint64_t buttons) { mouse_state_.buttons = buttons; }
void SendMouseMove(float x, float y);
void SendMouseDown(float x, float y);
void SendMouseUp(float x, float y);
void SendMouseLeave();
void SetEventPhaseFromCursorButtonState(UIWidgetsPointerEvent* event_data);
void SendPointerEventWithData(const UIWidgetsPointerEvent& event_data);
Mono_Handle handle_;
UIWidgetsWindowType window_type_;
EntrypointCallback entrypoint_callback_;
std::unique_ptr<UnitySurfaceManager> surface_manager_;
GLuint fbo_ = 0;
std::unique_ptr<GfxWorkerTaskRunner> gfx_worker_task_runner_;
std::unique_ptr<CocoaTaskRunner> task_runner_;
UIWidgetsEngine engine_ = nullptr;
std::vector<intptr_t> vsync_batons_;
MouseState mouse_state_;
bool process_events_ = false;
};
} // namespace uiwidgets

69
engine/src/shell/platform/unity/android/android_task_runner.h


#pragma once
#include <flutter/fml/closure.h>
#include <chrono>
#include <deque>
#include <map>
#include <mutex>
#include <queue>
#include "shell/platform/embedder/embedder.h"
#include <flutter/fml/memory/ref_counted.h>
#include "runtime/mono_api.h"
namespace uiwidgets {
class CocoaTaskRunner {
public:
using TaskExpiredCallback = std::function<void(const UIWidgetsTask*)>;
CocoaTaskRunner(pid_t threadId, const TaskExpiredCallback& on_task_expired);
~CocoaTaskRunner();
std::chrono::nanoseconds ProcessTasks();
// Post a Flutter engine tasks to the event loop for delayed execution.
void PostTask(UIWidgetsTask uiwidgets_task,
uint64_t uiwidgets_target_time_nanos);
void AddTaskObserver(intptr_t key, const fml::closure& callback);
void RemoveTaskObserver(intptr_t key);
bool RunsTasksOnCurrentThread();
FML_DISALLOW_COPY_AND_ASSIGN(CocoaTaskRunner);
private:
using TaskTimePoint = std::chrono::steady_clock::time_point;
struct Task {
uint64_t order;
TaskTimePoint fire_time;
UIWidgetsTask task;
struct Comparer {
bool operator()(const Task& a, const Task& b) {
if (a.fire_time == b.fire_time) {
return a.order > b.order;
}
return a.fire_time > b.fire_time;
}
};
};
TaskExpiredCallback on_task_expired_;
std::mutex task_queue_mutex_;
std::priority_queue<Task, std::deque<Task>, Task::Comparer> task_queue_;
pid_t threadId;
using TaskObservers = std::map<intptr_t, fml::closure>;
TaskObservers task_observers_;
static TaskTimePoint TimePointFromUIWidgetsTime(
uint64_t uiwidgets_target_time_nanos);
};
} // namespace uiwidgets

113
engine/src/shell/platform/unity/android/android_task_runner.cc


#include "android_task_runner.h"
#include <flutter/fml/time/time_point.h>
#include <atomic>
#include <utility>
namespace uiwidgets {
CocoaTaskRunner::CocoaTaskRunner(pid_t threadId, const TaskExpiredCallback& on_task_expired)
: on_task_expired_(std::move(on_task_expired)),
threadId(threadId)
{}
CocoaTaskRunner::~CocoaTaskRunner() = default;
std::chrono::nanoseconds CocoaTaskRunner::ProcessTasks() {
const TaskTimePoint now = TaskTimePoint::clock::now();
std::vector<UIWidgetsTask> expired_tasks;
// Process expired tasks.
{
std::lock_guard<std::mutex> lock(task_queue_mutex_);
while (!task_queue_.empty()) {
const auto& top = task_queue_.top();
// If this task (and all tasks after this) has not yet expired, there is
// nothing more to do. Quit iterating.
if (top.fire_time > now) {
break;
}
// Make a record of the expired task. Do NOT service the task here
// because we are still holding onto the task queue mutex. We don't want
// other threads to block on posting tasks onto this thread till we are
// done processing expired tasks.
expired_tasks.push_back(task_queue_.top().task);
// Remove the tasks from the delayed tasks queue.
task_queue_.pop();
}
}
for (const auto& observer : task_observers_) {
observer.second();
}
// Fire expired tasks.
{
// Flushing tasks here without holing onto the task queue mutex.
for (const auto& task : expired_tasks) {
on_task_expired_(&task);
for (const auto& observer : task_observers_) {
observer.second();
}
}
}
if (!expired_tasks.empty()) {
return ProcessTasks();
}
// Calculate duration to sleep for on next iteration.
{
std::lock_guard<std::mutex> lock(task_queue_mutex_);
const auto next_wake = task_queue_.empty() ? TaskTimePoint::max()
: task_queue_.top().fire_time;
return std::min(next_wake - now, std::chrono::nanoseconds::max());
}
}
CocoaTaskRunner::TaskTimePoint CocoaTaskRunner::TimePointFromUIWidgetsTime(
uint64_t uiwidgets_target_time_nanos) {
const auto fml_now = fml::TimePoint::Now().ToEpochDelta().ToNanoseconds();
if (uiwidgets_target_time_nanos <= (uint64_t)fml_now) {
return {};
}
const auto uiwidgets_duration = uiwidgets_target_time_nanos - fml_now;
const auto now = TaskTimePoint::clock::now();
return now + std::chrono::nanoseconds(uiwidgets_duration);
}
void CocoaTaskRunner::PostTask(UIWidgetsTask uiwidgets_task,
uint64_t uiwidgets_target_time_nanos) {
static std::atomic_uint64_t sGlobalTaskOrder(0);
Task task;
task.order = ++sGlobalTaskOrder;
task.fire_time = TimePointFromUIWidgetsTime(uiwidgets_target_time_nanos);
task.task = uiwidgets_task;
{
std::lock_guard<std::mutex> lock(task_queue_mutex_);
task_queue_.push(task);
}
}
bool CocoaTaskRunner::RunsTasksOnCurrentThread(){
pid_t id = gettid();
return threadId == id;
}
void CocoaTaskRunner::AddTaskObserver(intptr_t key,
const fml::closure& callback) {
task_observers_[key] = callback;
}
void CocoaTaskRunner::RemoveTaskObserver(intptr_t key) {
task_observers_.erase(key);
}
} // namespace uiwidgets

3
com.unity.uiwidgets/Runtime/service.meta


fileFormatVersion: 2
guid: 355cc83db152457b8eb6da935c588fbc
timeCreated: 1536566821
正在加载...
取消
保存