浏览代码

add android platform

/siyaoH-1.17-PlatformMessage
siyao 4 年前
当前提交
a08b4edb
共有 14 个文件被更改,包括 1259 次插入14 次删除
  1. 10
      engine/build.py
  2. 3
      engine/src/engine.cc
  3. 5
      engine/src/runtime/mono_api.cc
  4. 2
      engine/src/shell/gpu/gpu_surface_gl.cc
  5. 10
      engine/src/shell/platform/unity/gfx_worker_task_runner.cc
  6. 106
      engine/src/shell/platform/unity/darwin/android/cocoa_task_runner.cc
  7. 66
      engine/src/shell/platform/unity/darwin/android/cocoa_task_runner.h
  8. 504
      engine/src/shell/platform/unity/darwin/android/uiwidgets_panel.cc
  9. 103
      engine/src/shell/platform/unity/darwin/android/uiwidgets_panel.h
  10. 94
      engine/src/shell/platform/unity/darwin/android/uiwidgets_system.cc
  11. 76
      engine/src/shell/platform/unity/darwin/android/uiwidgets_system.h
  12. 239
      engine/src/shell/platform/unity/darwin/android/unity_surface_manager.cc
  13. 55
      engine/src/shell/platform/unity/darwin/android/unity_surface_manager.h

10
engine/build.py


)
stdout, stderr = process.communicate()
if log:
print("out:", stdout)
print("err:", stderr)
print("out:"+stdout)
print("err:"+stderr)
return stdout, stderr
linkOnly = len(sys.argv) > 1

clang = FLUTTER_ROOT+"/buildtools/mac-x64/clang/bin/clang++"
codeFiles = [
# "src/shell/platform/unity/darwin/android/uiwidgets_system.cc",
"src/assets/asset_manager.cc",
"src/assets/asset_manager.h",
"src/assets/asset_resolver.h",

continue
if buildEngine and name != 'engine':
continue
print(codeFile)
# process = subprocess.Popen(
# buildScript, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# stdout, stderr = process.communicate()
# print(codeFile)
if len(stderr) > 0:
print(stdout)
print(stderr)

3
engine/src/engine.cc


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

5
engine/src/runtime/mono_api.cc


}
#endif
#ifdef __ANDROID__
uint64_t GetCurrentThreadId() {
return gettid();
}
#endif
namespace uiwidgets {
FML_THREAD_LOCAL fml::ThreadLocalUniquePtr<Mono_Isolate> tls_isolate;

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


{
TRACE_EVENT0("uiwidgets", "SkCanvas::Flush");
onscreen_surface_->getCanvas()->flush();
onscreen_surface_->getContext()->submit(true);
// onscreen_surface_->getContext()->submit(true);
}
if (!delegate_->GLContextPresent()) {

10
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 {
on_task_expired(&uiwidgets_task);
});
// UIWidgetsSystem::GetInstancePtr()->PostTaskToGfxWorker(
// [&on_task_expired = on_task_expired_, uiwidgets_task]() -> void {
// on_task_expired(&uiwidgets_task);
// });
}
} // namespace uiwidgets

106
engine/src/shell/platform/unity/darwin/android/cocoa_task_runner.cc


#include "cocoa_task_runner.h"
#include <flutter/fml/time/time_point.h>
#include <atomic>
#include <utility>
namespace uiwidgets {
CocoaTaskRunner::CocoaTaskRunner(const TaskExpiredCallback& on_task_expired)
: on_task_expired_(std::move(on_task_expired)) {}
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 <= 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);
}
}
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

66
engine/src/shell/platform/unity/darwin/android/cocoa_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(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);
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_;
using TaskObservers = std::map<intptr_t, fml::closure>;
TaskObservers task_observers_;
static TaskTimePoint TimePointFromUIWidgetsTime(
uint64_t uiwidgets_target_time_nanos);
};
} // namespace uiwidgets

504
engine/src/shell/platform/unity/darwin/android/uiwidgets_panel.cc


#include "uiwidgets_panel.h"
#include <Windows.h>
#include <flutter/fml/synchronization/waitable_event.h>
#include <include\utils\SkBase64.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 "unity_external_texture_gl.h"
namespace uiwidgets {
fml::RefPtr<UIWidgetsPanel> UIWidgetsPanel::Create(
Mono_Handle handle, EntrypointCallback entrypoint_callback) {
return fml::MakeRefCounted<UIWidgetsPanel>(handle, entrypoint_callback);
}
UIWidgetsPanel::UIWidgetsPanel(Mono_Handle handle,
EntrypointCallback entrypoint_callback)
: handle_(handle), entrypoint_callback_(entrypoint_callback) {}
UIWidgetsPanel::~UIWidgetsPanel() = default;
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<Win32TaskRunner>(
GetCurrentThreadId(), [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<Win32TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
};
ui_task_runner.post_task_callback = [](UIWidgetsTask task,
uint64_t target_time_nanos,
void* user_data) -> void {
static_cast<Win32TaskRunner*>(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;
// std::string icu_path = std::string(streaming_assets_path) + "/icudtl.dat";
// args.icu_data_path = icu_path.c_str();
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) {
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) {
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,
UIWidgetsPanel::EntrypointCallback entrypoint_callback) {
const auto panel = UIWidgetsPanel::Create(handle, entrypoint_callback);
panel->AddRef();
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(); }
} // namespace uiwidgets

103
engine/src/shell/platform/unity/darwin/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 "cocoa_task_runner.h"
namespace uiwidgets {
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, 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();
private:
UIWidgetsPanel(Mono_Handle handle, 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_;
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

94
engine/src/shell/platform/unity/darwin/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

76
engine/src/shell/platform/unity/darwin/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"
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);
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) {
GetInstancePtr()->GfxWorkerCallback(eventId, data);
}
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

239
engine/src/shell/platform/unity/darwin/android/unity_surface_manager.cc


#include "unity_surface_manager.h"
#include <d3d11.h>
#include <dxgi.h>
#include <flutter/fml/logging.h>
#include "Unity/IUnityGraphics.h"
#include "Unity/IUnityGraphicsD3D11.h"
namespace uiwidgets {
UnitySurfaceManager::UnitySurfaceManager(IUnityInterfaces* unity_interfaces)
: egl_display_(EGL_NO_DISPLAY),
egl_context_(EGL_NO_CONTEXT),
egl_resource_context_(EGL_NO_CONTEXT),
egl_config_(nullptr) {
initialize_succeeded_ = Initialize(unity_interfaces);
}
UnitySurfaceManager::~UnitySurfaceManager() { CleanUp(); }
GLuint UnitySurfaceManager::CreateRenderSurface(void* native_texture_ptr) {
ID3D11Texture2D* d3d11_texture =
static_cast<ID3D11Texture2D*>(native_texture_ptr);
IDXGIResource* image_resource;
HRESULT hr = d3d11_texture->QueryInterface(
__uuidof(IDXGIResource), reinterpret_cast<void**>(&image_resource));
FML_CHECK(SUCCEEDED(hr)) << "UnitySurfaceManager: QueryInterface() failed";
HANDLE shared_image_handle;
hr = image_resource->GetSharedHandle(&shared_image_handle);
FML_CHECK(SUCCEEDED(hr)) << "UnitySurfaceManager: GetSharedHandle() failed";
image_resource->Release();
FML_CHECK(shared_image_handle != nullptr)
<< "UnitySurfaceManager: shared_image_handle is nullptr, miscFlags "
"D3D11_RESOURCE_MISC_SHARED is needed";
IDXGIResource* dxgi_resource;
hr = d3d11_device_->OpenSharedResource(
shared_image_handle, __uuidof(ID3D11Resource),
reinterpret_cast<void**>(&dxgi_resource));
FML_CHECK(SUCCEEDED(hr))
<< "UnitySurfaceManager: failed to open shared resource";
ID3D11Texture2D* image_texture;
hr = dxgi_resource->QueryInterface(__uuidof(ID3D11Texture2D),
reinterpret_cast<void**>(&image_texture));
FML_CHECK(SUCCEEDED(hr))
<< "UnitySurfaceManager: failed to query interface ID3D11Texture2D";
dxgi_resource->Release();
const EGLint attribs[] = {EGL_NONE};
FML_DCHECK(fbo_egl_image_ == nullptr);
fbo_egl_image_ =
eglCreateImageKHR(egl_display_, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
static_cast<EGLClientBuffer>(image_texture), attribs);
FML_CHECK(fbo_egl_image_ != EGL_NO_IMAGE_KHR);
image_texture->Release();
GLint old_texture_binding_2d;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture_binding_2d);
FML_DCHECK(fbo_texture_ == 0);
glGenTextures(1, &fbo_texture_);
glBindTexture(GL_TEXTURE_2D, fbo_texture_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, fbo_egl_image_);
glBindTexture(GL_TEXTURE_2D, old_texture_binding_2d);
GLint old_framebuffer_binding;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_framebuffer_binding);
FML_DCHECK(fbo_ == 0);
glGenFramebuffers(1, &fbo_);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
fbo_texture_, 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;
FML_DCHECK(fbo_texture_ != 0);
glDeleteTextures(1, &fbo_texture_);
fbo_texture_ = 0;
FML_DCHECK(fbo_egl_image_ != nullptr);
eglDestroyImageKHR(egl_display_, fbo_egl_image_);
fbo_egl_image_ = nullptr;
}
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;
}
bool UnitySurfaceManager::Initialize(IUnityInterfaces* unity_interfaces) {
IUnityGraphics* graphics = unity_interfaces->Get<IUnityGraphics>();
FML_CHECK(graphics->GetRenderer() == kUnityGfxRendererD3D11)
<< "Renderer type is invalid";
IUnityGraphicsD3D11* d3d11 = unity_interfaces->Get<IUnityGraphicsD3D11>();
ID3D11Device* d3d11_device = d3d11->GetDevice();
IDXGIDevice* dxgi_device;
HRESULT hr = d3d11_device->QueryInterface(
__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgi_device));
FML_CHECK(SUCCEEDED(hr)) << "d3d11_device->QueryInterface(...) failed";
IDXGIAdapter* dxgi_adapter;
hr = dxgi_device->GetAdapter(&dxgi_adapter);
FML_CHECK(SUCCEEDED(hr)) << "dxgi_adapter->GetAdapter(...) failed";
dxgi_device->Release();
DXGI_ADAPTER_DESC adapter_desc;
hr = dxgi_adapter->GetDesc(&adapter_desc);
FML_CHECK(SUCCEEDED(hr)) << "dxgi_adapter->GetDesc(...) failed";
dxgi_adapter->Release();
EGLint displayAttribs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE,
adapter_desc.AdapterLuid.HighPart,
EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE,
adapter_desc.AdapterLuid.LowPart,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE};
egl_display_ = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
EGL_DEFAULT_DISPLAY, displayAttribs);
FML_CHECK(egl_display_ != EGL_NO_DISPLAY)
<< "EGL: Failed to get a compatible EGLdisplay";
if (eglInitialize(egl_display_, nullptr, nullptr) == EGL_FALSE) {
FML_CHECK(false) << "EGL: Failed to initialize EGL";
}
EGLAttrib egl_device = 0;
eglQueryDisplayAttribEXT(egl_display_, EGL_DEVICE_EXT, &egl_device);
EGLAttrib angle_device = 0;
eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(egl_device),
EGL_D3D11_DEVICE_ANGLE, &angle_device);
d3d11_device_ = reinterpret_cast<ID3D11Device*>(angle_device);
const EGLint configAttributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8,
EGL_NONE};
EGLint numConfigs = 0;
if (eglChooseConfig(egl_display_, configAttributes, &egl_config_, 1,
&numConfigs) == EGL_FALSE ||
numConfigs == 0) {
FML_CHECK(false) << "EGL: Failed to choose first context";
}
const EGLint display_context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE};
egl_context_ = eglCreateContext(egl_display_, egl_config_, EGL_NO_CONTEXT,
display_context_attributes);
if (egl_context_ == EGL_NO_CONTEXT) {
FML_CHECK(false) << "EGL: Failed to create EGL context";
}
egl_resource_context_ = eglCreateContext(
egl_display_, egl_config_, egl_context_, display_context_attributes);
if (egl_resource_context_ == EGL_NO_CONTEXT) {
FML_CHECK(false) << "EGL: Failed to create EGL resource context";
}
return true;
}
void UnitySurfaceManager::CleanUp() {
EGLBoolean result = EGL_FALSE;
if (egl_display_ != EGL_NO_DISPLAY && egl_context_ != EGL_NO_CONTEXT) {
result = eglDestroyContext(egl_display_, egl_context_);
egl_context_ = EGL_NO_CONTEXT;
if (result == EGL_FALSE) {
FML_LOG(ERROR) << "EGL: Failed to destroy context";
}
}
d3d11_device_ = nullptr;
if (egl_display_ != EGL_NO_DISPLAY &&
egl_resource_context_ != EGL_NO_CONTEXT) {
result = eglDestroyContext(egl_display_, egl_resource_context_);
egl_resource_context_ = EGL_NO_CONTEXT;
if (result == EGL_FALSE) {
FML_LOG(ERROR) << "EGL : Failed to destroy resource context";
}
}
if (egl_display_ != EGL_NO_DISPLAY) {
result = eglTerminate(egl_display_);
egl_display_ = EGL_NO_DISPLAY;
if (result == EGL_FALSE) {
FML_LOG(ERROR) << "EGL : Failed to terminate EGL";
}
}
}
} // namespace uiwidgets

55
engine/src/shell/platform/unity/darwin/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 <d3d11.h>
// #include <windows.h>
#include <cstdint>
#include "Unity/IUnityInterface.h"
#include "flutter/fml/macros.h"
namespace uiwidgets {
class UnitySurfaceManager {
public:
UnitySurfaceManager(IUnityInterfaces* unity_interfaces);
~UnitySurfaceManager();
GLuint CreateRenderSurface(void* native_texture_ptr);
void DestroyRenderSurface();
bool ClearCurrent();
bool MakeCurrent(const EGLSurface surface);
bool MakeResourceCurrent();
EGLDisplay GetEGLDisplay() const { return egl_display_; }
ID3D11Device* GetD3D11Device() const { return d3d11_device_; }
FML_DISALLOW_COPY_AND_ASSIGN(UnitySurfaceManager);
private:
bool Initialize(IUnityInterfaces* unity_interfaces);
void CleanUp();
EGLDisplay egl_display_;
EGLContext egl_context_;
EGLContext egl_resource_context_;
EGLConfig egl_config_;
bool initialize_succeeded_;
ID3D11Device* d3d11_device_;
EGLImage fbo_egl_image_ = nullptr;
GLuint fbo_texture_ = 0;
GLuint fbo_ = 0;
};
} // namespace uiwidgets
正在加载...
取消
保存