Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
4e344e6c
E
engine
项目概览
sxychenjing
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
4e344e6c
编写于
6月 29, 2019
作者:
C
Chinmay Garde
提交者:
GitHub
6月 29, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Wire up custom event loop interop for the GLFW embedder. (#9089)
上级
54c62263
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
253 addition
and
14 deletion
+253
-14
ci/licenses_golden/licenses_flutter
ci/licenses_golden/licenses_flutter
+2
-0
shell/platform/glfw/BUILD.gn
shell/platform/glfw/BUILD.gn
+7
-0
shell/platform/glfw/flutter_glfw.cc
shell/platform/glfw/flutter_glfw.cc
+53
-14
shell/platform/glfw/glfw_event_loop.cc
shell/platform/glfw/glfw_event_loop.cc
+114
-0
shell/platform/glfw/glfw_event_loop.h
shell/platform/glfw/glfw_event_loop.h
+73
-0
tools/gn
tools/gn
+4
-0
未找到文件。
ci/licenses_golden/licenses_flutter
浏览文件 @
4e344e6c
...
@@ -918,6 +918,8 @@ FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutte
...
@@ -918,6 +918,8 @@ FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutte
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window_controller.h
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/flutter_window_controller.h
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/plugin_registrar_glfw.h
FILE: ../../../flutter/shell/platform/glfw/client_wrapper/include/flutter/plugin_registrar_glfw.h
FILE: ../../../flutter/shell/platform/glfw/flutter_glfw.cc
FILE: ../../../flutter/shell/platform/glfw/flutter_glfw.cc
FILE: ../../../flutter/shell/platform/glfw/glfw_event_loop.cc
FILE: ../../../flutter/shell/platform/glfw/glfw_event_loop.h
FILE: ../../../flutter/shell/platform/glfw/key_event_handler.cc
FILE: ../../../flutter/shell/platform/glfw/key_event_handler.cc
FILE: ../../../flutter/shell/platform/glfw/key_event_handler.h
FILE: ../../../flutter/shell/platform/glfw/key_event_handler.h
FILE: ../../../flutter/shell/platform/glfw/keyboard_hook_handler.h
FILE: ../../../flutter/shell/platform/glfw/keyboard_hook_handler.h
...
...
shell/platform/glfw/BUILD.gn
浏览文件 @
4e344e6c
...
@@ -33,6 +33,8 @@ source_set("flutter_glfw_headers") {
...
@@ -33,6 +33,8 @@ source_set("flutter_glfw_headers") {
source_set("flutter_glfw") {
source_set("flutter_glfw") {
sources = [
sources = [
"flutter_glfw.cc",
"flutter_glfw.cc",
"glfw_event_loop.cc",
"glfw_event_loop.h",
"key_event_handler.cc",
"key_event_handler.cc",
"key_event_handler.h",
"key_event_handler.h",
"keyboard_hook_handler.h",
"keyboard_hook_handler.h",
...
@@ -65,6 +67,11 @@ source_set("flutter_glfw") {
...
@@ -65,6 +67,11 @@ source_set("flutter_glfw") {
"$flutter_root/shell/platform/linux/config:gtk3",
"$flutter_root/shell/platform/linux/config:gtk3",
"$flutter_root/shell/platform/linux/config:x11",
"$flutter_root/shell/platform/linux/config:x11",
]
]
} else if (is_mac) {
libs = [
"CoreVideo.framework",
"IOKit.framework",
]
}
}
}
}
...
...
shell/platform/glfw/flutter_glfw.cc
浏览文件 @
4e344e6c
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h"
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/glfw/glfw_event_loop.h"
#include "flutter/shell/platform/glfw/key_event_handler.h"
#include "flutter/shell/platform/glfw/key_event_handler.h"
#include "flutter/shell/platform/glfw/keyboard_hook_handler.h"
#include "flutter/shell/platform/glfw/keyboard_hook_handler.h"
#include "flutter/shell/platform/glfw/platform_handler.h"
#include "flutter/shell/platform/glfw/platform_handler.h"
...
@@ -79,8 +80,11 @@ struct FlutterDesktopWindowControllerState {
...
@@ -79,8 +80,11 @@ struct FlutterDesktopWindowControllerState {
// Handler for the flutter/platform channel.
// Handler for the flutter/platform channel.
std
::
unique_ptr
<
flutter
::
PlatformHandler
>
platform_handler
;
std
::
unique_ptr
<
flutter
::
PlatformHandler
>
platform_handler
;
// Whether or not the pointer has been added (or if tracking is enabled, has
// The event loop for the main thread that allows for delayed task execution.
// been added since it was last removed).
std
::
unique_ptr
<
flutter
::
GLFWEventLoop
>
event_loop
;
// Whether or not the pointer has been added (or if tracking is enabled,
// has been added since it was last removed).
bool
pointer_currently_added
=
false
;
bool
pointer_currently_added
=
false
;
// The screen coordinates per inch on the primary monitor. Defaults to a sane
// The screen coordinates per inch on the primary monitor. Defaults to a sane
...
@@ -489,11 +493,13 @@ static void GLFWErrorCallback(int error_code, const char* description) {
...
@@ -489,11 +493,13 @@ static void GLFWErrorCallback(int error_code, const char* description) {
// provided).
// provided).
//
//
// Returns a caller-owned pointer to the engine.
// Returns a caller-owned pointer to the engine.
static
FlutterEngine
RunFlutterEngine
(
GLFWwindow
*
window
,
static
FlutterEngine
RunFlutterEngine
(
GLFWwindow
*
window
,
const
char
*
assets_path
,
const
char
*
assets_path
,
const
char
*
icu_data_path
,
const
char
*
icu_data_path
,
const
char
**
arguments
,
const
char
**
arguments
,
size_t
arguments_count
)
{
size_t
arguments_count
,
const
FlutterCustomTaskRunners
*
custom_task_runners
)
{
// FlutterProjectArgs is expecting a full argv, so when processing it for
// FlutterProjectArgs is expecting a full argv, so when processing it for
// flags the first item is treated as the executable and ignored. Add a dummy
// flags the first item is treated as the executable and ignored. Add a dummy
// value so that all provided arguments are used.
// value so that all provided arguments are used.
...
@@ -528,6 +534,7 @@ static FlutterEngine RunFlutterEngine(GLFWwindow* window,
...
@@ -528,6 +534,7 @@ static FlutterEngine RunFlutterEngine(GLFWwindow* window,
args
.
command_line_argc
=
static_cast
<
int
>
(
argv
.
size
());
args
.
command_line_argc
=
static_cast
<
int
>
(
argv
.
size
());
args
.
command_line_argv
=
&
argv
[
0
];
args
.
command_line_argv
=
&
argv
[
0
];
args
.
platform_message_callback
=
GLFWOnFlutterPlatformMessage
;
args
.
platform_message_callback
=
GLFWOnFlutterPlatformMessage
;
args
.
custom_task_runners
=
custom_task_runners
;
FlutterEngine
engine
=
nullptr
;
FlutterEngine
engine
=
nullptr
;
auto
result
=
auto
result
=
FlutterEngineRun
(
FLUTTER_ENGINE_VERSION
,
&
config
,
&
args
,
window
,
&
engine
);
FlutterEngineRun
(
FLUTTER_ENGINE_VERSION
,
&
config
,
&
args
,
window
,
&
engine
);
...
@@ -578,9 +585,38 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
...
@@ -578,9 +585,38 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
// GLFWMakeResourceContextCurrent immediately.
// GLFWMakeResourceContextCurrent immediately.
state
->
resource_window
=
CreateShareWindowForWindow
(
window
);
state
->
resource_window
=
CreateShareWindowForWindow
(
window
);
// Create an event loop for the window. It is not running yet.
state
->
event_loop
=
std
::
make_unique
<
flutter
::
GLFWEventLoop
>
(
std
::
this_thread
::
get_id
(),
// main GLFW thread
[
state
=
state
.
get
()](
const
auto
*
task
)
{
if
(
FlutterEngineRunTask
(
state
->
engine
,
task
)
!=
kSuccess
)
{
std
::
cerr
<<
"Could not post an engine task."
<<
std
::
endl
;
}
});
// Configure task runner interop.
FlutterTaskRunnerDescription
platform_task_runner
=
{};
platform_task_runner
.
struct_size
=
sizeof
(
FlutterTaskRunnerDescription
);
platform_task_runner
.
user_data
=
state
.
get
();
platform_task_runner
.
runs_task_on_current_thread_callback
=
[](
void
*
state
)
->
bool
{
return
reinterpret_cast
<
FlutterDesktopWindowControllerState
*>
(
state
)
->
event_loop
->
RunsTasksOnCurrentThread
();
};
platform_task_runner
.
post_task_callback
=
[](
FlutterTask
task
,
uint64_t
target_time_nanos
,
void
*
state
)
->
void
{
reinterpret_cast
<
FlutterDesktopWindowControllerState
*>
(
state
)
->
event_loop
->
PostTask
(
task
,
target_time_nanos
);
};
FlutterCustomTaskRunners
custom_task_runners
=
{};
custom_task_runners
.
struct_size
=
sizeof
(
FlutterCustomTaskRunners
);
custom_task_runners
.
platform_task_runner
=
&
platform_task_runner
;
// Start the engine.
// Start the engine.
state
->
engine
=
RunFlutterEngine
(
window
,
assets_path
,
icu_data_path
,
state
->
engine
=
arguments
,
argument_count
);
RunFlutterEngine
(
window
,
assets_path
,
icu_data_path
,
arguments
,
argument_count
,
&
custom_task_runners
);
if
(
state
->
engine
==
nullptr
)
{
if
(
state
->
engine
==
nullptr
)
{
return
nullptr
;
return
nullptr
;
}
}
...
@@ -704,15 +740,17 @@ void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) {
...
@@ -704,15 +740,17 @@ void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) {
// Necessary for GTK thread safety.
// Necessary for GTK thread safety.
XInitThreads
();
XInitThreads
();
#endif
#endif
while
(
!
glfwWindowShouldClose
(
window
))
{
while
(
!
glfwWindowShouldClose
(
window
))
{
glfwPollEvents
();
auto
wait_duration
=
std
::
chrono
::
milliseconds
::
max
();
#ifdef FLUTTER_USE_GTK
#ifdef FLUTTER_USE_GTK
// If we are not using GTK, there is no point in waking up.
wait_duration
=
std
::
chrono
::
milliseconds
(
10
);
if
(
gtk_events_pending
())
{
if
(
gtk_events_pending
())
{
gtk_main_iteration
();
gtk_main_iteration
();
}
}
#endif
#endif
// TODO(awdavies): This will be deprecated soon.
controller
->
event_loop
->
WaitForEvents
(
wait_duration
);
__FlutterEngineFlushPendingTasksNow
();
}
}
FlutterDesktopDestroyWindow
(
controller
);
FlutterDesktopDestroyWindow
(
controller
);
}
}
...
@@ -738,8 +776,9 @@ FlutterDesktopEngineRef FlutterDesktopRunEngine(const char* assets_path,
...
@@ -738,8 +776,9 @@ FlutterDesktopEngineRef FlutterDesktopRunEngine(const char* assets_path,
const
char
*
icu_data_path
,
const
char
*
icu_data_path
,
const
char
**
arguments
,
const
char
**
arguments
,
size_t
argument_count
)
{
size_t
argument_count
)
{
auto
engine
=
RunFlutterEngine
(
nullptr
,
assets_path
,
icu_data_path
,
arguments
,
auto
engine
=
argument_count
);
RunFlutterEngine
(
nullptr
,
assets_path
,
icu_data_path
,
arguments
,
argument_count
,
nullptr
/* custom task runners */
);
if
(
engine
==
nullptr
)
{
if
(
engine
==
nullptr
)
{
return
nullptr
;
return
nullptr
;
}
}
...
...
shell/platform/glfw/glfw_event_loop.cc
0 → 100644
浏览文件 @
4e344e6c
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/glfw/glfw_event_loop.h"
#include <GLFW/glfw3.h>
#include <atomic>
#include <utility>
namespace
flutter
{
GLFWEventLoop
::
GLFWEventLoop
(
std
::
thread
::
id
main_thread_id
,
TaskExpiredCallback
on_task_expired
)
:
main_thread_id_
(
main_thread_id
),
on_task_expired_
(
std
::
move
(
on_task_expired
))
{}
GLFWEventLoop
::~
GLFWEventLoop
()
=
default
;
bool
GLFWEventLoop
::
RunsTasksOnCurrentThread
()
const
{
return
std
::
this_thread
::
get_id
()
==
main_thread_id_
;
}
void
GLFWEventLoop
::
WaitForEvents
(
std
::
chrono
::
nanoseconds
max_wait
)
{
const
auto
now
=
TaskTimePoint
::
clock
::
now
();
std
::
vector
<
FlutterTask
>
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
();
}
}
// Fire expired tasks.
{
// Flushing tasks here without holing onto the task queue mutex.
for
(
const
auto
&
task
:
expired_tasks
)
{
on_task_expired_
(
&
task
);
}
}
// Sleep till the next task needs to be processed. If a new task comes
// along, the wait in GLFW will be resolved early because PostTask posts an
// empty event.
{
// Make sure the seconds are not integral.
using
Seconds
=
std
::
chrono
::
duration
<
double
,
std
::
ratio
<
1
>>
;
std
::
lock_guard
<
std
::
mutex
>
lock
(
task_queue_mutex_
);
const
auto
next_wake
=
task_queue_
.
empty
()
?
TaskTimePoint
::
max
()
:
task_queue_
.
top
().
fire_time
;
const
auto
duration_to_wait
=
std
::
chrono
::
duration_cast
<
Seconds
>
(
std
::
min
(
next_wake
-
now
,
max_wait
));
if
(
duration_to_wait
.
count
()
>
0.0
)
{
::
glfwWaitEventsTimeout
(
duration_to_wait
.
count
());
}
else
{
// Avoid engine task priority inversion by making sure GLFW events are
// always processed even when there is no need to wait for pending engine
// tasks.
::
glfwPollEvents
();
}
}
}
GLFWEventLoop
::
TaskTimePoint
GLFWEventLoop
::
TimePointFromFlutterTime
(
uint64_t
flutter_target_time_nanos
)
{
const
auto
now
=
TaskTimePoint
::
clock
::
now
();
const
auto
flutter_duration
=
flutter_target_time_nanos
-
FlutterEngineGetCurrentTime
();
return
now
+
std
::
chrono
::
nanoseconds
(
flutter_duration
);
}
void
GLFWEventLoop
::
PostTask
(
FlutterTask
flutter_task
,
uint64_t
flutter_target_time_nanos
)
{
static
std
::
atomic_uint64_t
sGlobalTaskOrder
(
0
);
Task
task
;
task
.
order
=
++
sGlobalTaskOrder
;
task
.
fire_time
=
TimePointFromFlutterTime
(
flutter_target_time_nanos
);
task
.
task
=
flutter_task
;
{
std
::
lock_guard
<
std
::
mutex
>
lock
(
task_queue_mutex_
);
task_queue_
.
push
(
task
);
// Make sure the queue mutex is unlocked before waking up the loop. In case
// the wake causes this thread to be descheduled for the primary thread to
// process tasks, the acquisition of the lock on that thread while holding
// the lock here momentarily till the end of the scope is a pessimization.
}
::
glfwPostEmptyEvent
();
}
}
// namespace flutter
shell/platform/glfw/glfw_event_loop.h
0 → 100644
浏览文件 @
4e344e6c
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_GLFW_GLFW_EVENT_LOOP_H_
#define FLUTTER_SHELL_PLATFORM_GLFW_GLFW_EVENT_LOOP_H_
#include <chrono>
#include <deque>
#include <mutex>
#include <queue>
#include <thread>
#include "flutter/shell/platform/embedder/embedder.h"
namespace
flutter
{
// An event loop implementation that supports Flutter Engine tasks scheduling in
// the GLFW event loop.
class
GLFWEventLoop
{
public:
using
TaskExpiredCallback
=
std
::
function
<
void
(
const
FlutterTask
*
)
>
;
GLFWEventLoop
(
std
::
thread
::
id
main_thread_id
,
TaskExpiredCallback
on_task_expired
);
~
GLFWEventLoop
();
// Returns if the current thread is the thread used by the GLFW event loop.
bool
RunsTasksOnCurrentThread
()
const
;
// Wait for an any GLFW or pending Flutter Engine events and returns when
// either is encountered. Expired engine events are processed. The optional
// timeout should only be used when non-GLFW or engine events need to be
// processed in a polling manner.
void
WaitForEvents
(
std
::
chrono
::
nanoseconds
max_wait
=
std
::
chrono
::
nanoseconds
::
max
());
// Post a Flutter engine tasks to the event loop for delayed execution.
void
PostTask
(
FlutterTask
flutter_task
,
uint64_t
flutter_target_time_nanos
);
private:
using
TaskTimePoint
=
std
::
chrono
::
steady_clock
::
time_point
;
struct
Task
{
uint64_t
order
;
TaskTimePoint
fire_time
;
FlutterTask
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
;
}
};
};
std
::
thread
::
id
main_thread_id_
;
TaskExpiredCallback
on_task_expired_
;
std
::
mutex
task_queue_mutex_
;
std
::
priority_queue
<
Task
,
std
::
deque
<
Task
>
,
Task
::
Comparer
>
task_queue_
;
std
::
condition_variable
task_queue_cv_
;
GLFWEventLoop
(
const
GLFWEventLoop
&
)
=
delete
;
GLFWEventLoop
&
operator
=
(
const
GLFWEventLoop
&
)
=
delete
;
static
TaskTimePoint
TimePointFromFlutterTime
(
uint64_t
flutter_target_time_nanos
);
};
}
// namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_GLFW_GLFW_EVENT_LOOP_H_
tools/gn
浏览文件 @
4e344e6c
...
@@ -253,6 +253,7 @@ def to_gn_args(args):
...
@@ -253,6 +253,7 @@ def to_gn_args(args):
if
sys
.
platform
==
'darwin'
:
if
sys
.
platform
==
'darwin'
:
gn_args
[
'mac_sdk_path'
]
=
args
.
mac_sdk_path
gn_args
[
'mac_sdk_path'
]
=
args
.
mac_sdk_path
gn_args
[
'build_glfw_shell'
]
=
args
.
build_glfw_shell
if
gn_args
[
'mac_sdk_path'
]
==
''
:
if
gn_args
[
'mac_sdk_path'
]
==
''
:
gn_args
[
'mac_sdk_path'
]
=
os
.
getenv
(
'FLUTTER_MAC_SDK_PATH'
,
''
)
gn_args
[
'mac_sdk_path'
]
=
os
.
getenv
(
'FLUTTER_MAC_SDK_PATH'
,
''
)
...
@@ -323,6 +324,9 @@ def parse_args(args):
...
@@ -323,6 +324,9 @@ def parse_args(args):
help
=
'The IDE files to generate using GN. Use `gn gen help` and look for the --ide flag to'
+
help
=
'The IDE files to generate using GN. Use `gn gen help` and look for the --ide flag to'
+
' see supported IDEs. If this flag is not specified, a platform specific default is selected.'
)
' see supported IDEs. If this flag is not specified, a platform specific default is selected.'
)
parser
.
add_argument
(
'--build-glfw-shell'
,
dest
=
'build_glfw_shell'
,
default
=
False
,
action
=
'store_true'
,
help
=
'Force building the GLFW shell on desktop platforms where it is not built by default.'
)
return
parser
.
parse_args
(
args
)
return
parser
.
parse_args
(
args
)
def
main
(
argv
):
def
main
(
argv
):
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录