Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
sxychenjing
engine
提交
3930ac1b
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,发现更多精彩内容 >>
未验证
提交
3930ac1b
编写于
8月 19, 2020
作者:
D
Dan Field
提交者:
GitHub
8月 19, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Hint freed (#19842)
* Hint the VM when a layer or picture goes out of scope
上级
93a17907
变更
28
隐藏空白更改
内联
并排
Showing
28 changed file
with
247 addition
and
47 deletion
+247
-47
flow/compositor_context.cc
flow/compositor_context.cc
+10
-5
flow/compositor_context.h
flow/compositor_context.h
+20
-2
flow/layers/layer.cc
flow/layers/layer.cc
+3
-2
flow/layers/layer.h
flow/layers/layer.h
+5
-1
flow/layers/layer_tree.cc
flow/layers/layer_tree.cc
+1
-0
flow/layers/layer_tree_unittests.cc
flow/layers/layer_tree_unittests.cc
+15
-2
flow/layers/picture_layer.cc
flow/layers/picture_layer.cc
+12
-4
flow/layers/picture_layer.h
flow/layers/picture_layer.h
+2
-1
flow/layers/picture_layer_unittests.cc
flow/layers/picture_layer_unittests.cc
+10
-5
flow/raster_cache.cc
flow/raster_cache.cc
+8
-4
flow/raster_cache.h
flow/raster_cache.h
+9
-3
lib/ui/compositing/scene_builder.cc
lib/ui/compositing/scene_builder.cc
+1
-1
lib/ui/fixtures/ui_test.dart
lib/ui/fixtures/ui_test.dart
+57
-0
runtime/runtime_controller.cc
runtime/runtime_controller.cc
+4
-1
runtime/runtime_controller.h
runtime/runtime_controller.h
+4
-1
shell/common/engine.cc
shell/common/engine.cc
+6
-1
shell/common/engine.h
shell/common/engine.h
+9
-0
shell/common/rasterizer.cc
shell/common/rasterizer.cc
+1
-2
shell/common/rasterizer.h
shell/common/rasterizer.h
+1
-1
shell/common/shell.cc
shell/common/shell.cc
+10
-0
shell/common/shell.h
shell/common/shell.h
+7
-2
shell/common/shell_test.cc
shell/common/shell_test.cc
+34
-0
shell/common/shell_test.h
shell/common/shell_test.h
+1
-0
shell/common/shell_unittests.cc
shell/common/shell_unittests.cc
+7
-4
shell/common/skp_shader_warmup_unittests.cc
shell/common/skp_shader_warmup_unittests.cc
+4
-2
shell/platform/fuchsia/flutter/compositor_context.cc
shell/platform/fuchsia/flutter/compositor_context.cc
+3
-1
shell/platform/fuchsia/flutter/compositor_context.h
shell/platform/fuchsia/flutter/compositor_context.h
+2
-1
shell/platform/fuchsia/flutter/engine.cc
shell/platform/fuchsia/flutter/engine.cc
+1
-1
未找到文件。
flow/compositor_context.cc
浏览文件 @
3930ac1b
...
...
@@ -9,8 +9,10 @@
namespace
flutter
{
CompositorContext
::
CompositorContext
(
fml
::
Milliseconds
frame_budget
)
:
raster_time_
(
frame_budget
),
ui_time_
(
frame_budget
)
{}
CompositorContext
::
CompositorContext
(
Delegate
&
delegate
)
:
delegate_
(
delegate
),
raster_time_
(
delegate
.
GetFrameBudget
()),
ui_time_
(
delegate
.
GetFrameBudget
())
{}
CompositorContext
::~
CompositorContext
()
=
default
;
...
...
@@ -23,8 +25,11 @@ void CompositorContext::BeginFrame(ScopedFrame& frame,
}
void
CompositorContext
::
EndFrame
(
ScopedFrame
&
frame
,
bool
enable_instrumentation
)
{
raster_cache_
.
SweepAfterFrame
();
bool
enable_instrumentation
,
size_t
freed_hint
)
{
freed_hint
+=
raster_cache_
.
SweepAfterFrame
();
delegate_
.
OnCompositorEndFrame
(
freed_hint
);
if
(
enable_instrumentation
)
{
raster_time_
.
Stop
();
}
...
...
@@ -64,7 +69,7 @@ CompositorContext::ScopedFrame::ScopedFrame(
}
CompositorContext
::
ScopedFrame
::~
ScopedFrame
()
{
context_
.
EndFrame
(
*
this
,
instrumentation_enabled_
);
context_
.
EndFrame
(
*
this
,
instrumentation_enabled_
,
uncached_external_size_
);
}
RasterStatus
CompositorContext
::
ScopedFrame
::
Raster
(
...
...
flow/compositor_context.h
浏览文件 @
3930ac1b
...
...
@@ -37,6 +37,18 @@ enum class RasterStatus {
class
CompositorContext
{
public:
class
Delegate
{
public:
/// Called at the end of a frame with approximately how many bytes mightbe
/// freed if a GC ran now.
///
/// This method is called from the raster task runner.
virtual
void
OnCompositorEndFrame
(
size_t
freed_hint
)
=
0
;
/// Time limit for a smooth frame. See `Engine::GetDisplayRefreshRate`.
virtual
fml
::
Milliseconds
GetFrameBudget
()
=
0
;
};
class
ScopedFrame
{
public:
ScopedFrame
(
CompositorContext
&
context
,
...
...
@@ -67,6 +79,8 @@ class CompositorContext {
virtual
RasterStatus
Raster
(
LayerTree
&
layer_tree
,
bool
ignore_raster_cache
);
void
add_external_size
(
size_t
size
)
{
uncached_external_size_
+=
size
;
}
private:
CompositorContext
&
context_
;
GrDirectContext
*
gr_context_
;
...
...
@@ -76,11 +90,12 @@ class CompositorContext {
const
bool
instrumentation_enabled_
;
const
bool
surface_supports_readback_
;
fml
::
RefPtr
<
fml
::
RasterThreadMerger
>
raster_thread_merger_
;
size_t
uncached_external_size_
=
0
;
FML_DISALLOW_COPY_AND_ASSIGN
(
ScopedFrame
);
};
CompositorContext
(
fml
::
Milliseconds
frame_budget
=
fml
::
kDefaultFrameBudget
);
explicit
CompositorContext
(
Delegate
&
delegate
);
virtual
~
CompositorContext
();
...
...
@@ -108,6 +123,7 @@ class CompositorContext {
Stopwatch
&
ui_time
()
{
return
ui_time_
;
}
private:
Delegate
&
delegate_
;
RasterCache
raster_cache_
;
TextureRegistry
texture_registry_
;
Counter
frame_count_
;
...
...
@@ -116,7 +132,9 @@ class CompositorContext {
void
BeginFrame
(
ScopedFrame
&
frame
,
bool
enable_instrumentation
);
void
EndFrame
(
ScopedFrame
&
frame
,
bool
enable_instrumentation
);
void
EndFrame
(
ScopedFrame
&
frame
,
bool
enable_instrumentation
,
size_t
freed_hint
);
FML_DISALLOW_COPY_AND_ASSIGN
(
CompositorContext
);
};
...
...
flow/layers/layer.cc
浏览文件 @
3930ac1b
...
...
@@ -9,10 +9,11 @@
namespace
flutter
{
Layer
::
Layer
()
Layer
::
Layer
(
size_t
external_size
)
:
paint_bounds_
(
SkRect
::
MakeEmpty
()),
unique_id_
(
NextUniqueID
()),
needs_system_composite_
(
false
)
{}
needs_system_composite_
(
false
),
external_size_
(
external_size
)
{}
Layer
::~
Layer
()
=
default
;
...
...
flow/layers/layer.h
浏览文件 @
3930ac1b
...
...
@@ -67,13 +67,14 @@ struct PrerollContext {
// Informs whether a layer needs to be system composited.
bool
child_scene_layer_exists_below
=
false
;
#endif
size_t
uncached_external_size
=
0
;
};
// Represents a single composited layer. Created on the UI thread but then
// subquently used on the Rasterizer thread.
class
Layer
{
public:
Layer
();
Layer
(
size_t
external_size
=
0
);
virtual
~
Layer
();
virtual
void
Preroll
(
PrerollContext
*
context
,
const
SkMatrix
&
matrix
);
...
...
@@ -178,6 +179,8 @@ class Layer {
uint64_t
unique_id
()
const
{
return
unique_id_
;
}
size_t
external_size
()
const
{
return
external_size_
;
}
protected:
#if defined(LEGACY_FUCHSIA_EMBEDDER)
bool
child_layer_exists_below_
=
false
;
...
...
@@ -187,6 +190,7 @@ class Layer {
SkRect
paint_bounds_
;
uint64_t
unique_id_
;
bool
needs_system_composite_
;
size_t
external_size_
=
0
;
static
uint64_t
NextUniqueID
();
...
...
flow/layers/layer_tree.cc
浏览文件 @
3930ac1b
...
...
@@ -58,6 +58,7 @@ bool LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
device_pixel_ratio_
};
root_layer_
->
Preroll
(
&
context
,
frame
.
root_surface_transformation
());
frame
.
add_external_size
(
context
.
uncached_external_size
);
return
context
.
surface_needs_readback
;
}
...
...
flow/layers/layer_tree_unittests.cc
浏览文件 @
3930ac1b
...
...
@@ -15,11 +15,11 @@
namespace
flutter
{
namespace
testing
{
class
LayerTreeTest
:
public
CanvasTest
{
class
LayerTreeTest
:
public
CanvasTest
,
public
CompositorContext
::
Delegate
{
public:
LayerTreeTest
()
:
layer_tree_
(
SkISize
::
Make
(
64
,
64
),
1.0
f
),
compositor_context_
(
fml
::
kDefaultFrameBudget
),
compositor_context_
(
*
this
),
root_transform_
(
SkMatrix
::
Translate
(
1.0
f
,
1.0
f
)),
scoped_frame_
(
compositor_context_
.
AcquireFrame
(
nullptr
,
&
mock_canvas
(),
...
...
@@ -33,11 +33,24 @@ class LayerTreeTest : public CanvasTest {
CompositorContext
::
ScopedFrame
&
frame
()
{
return
*
scoped_frame_
.
get
();
}
const
SkMatrix
&
root_transform
()
{
return
root_transform_
;
}
// |CompositorContext::Delegate|
void
OnCompositorEndFrame
(
size_t
freed_hint
)
override
{
last_freed_hint_
=
freed_hint
;
}
// |CompositorContext::Delegate|
fml
::
Milliseconds
GetFrameBudget
()
override
{
return
fml
::
kDefaultFrameBudget
;
}
size_t
last_freed_hint
()
{
return
last_freed_hint_
;
}
private:
LayerTree
layer_tree_
;
CompositorContext
compositor_context_
;
SkMatrix
root_transform_
;
std
::
unique_ptr
<
CompositorContext
::
ScopedFrame
>
scoped_frame_
;
size_t
last_freed_hint_
=
0
;
};
TEST_F
(
LayerTreeTest
,
PaintingEmptyLayerDies
)
{
...
...
flow/layers/picture_layer.cc
浏览文件 @
3930ac1b
...
...
@@ -11,8 +11,10 @@ namespace flutter {
PictureLayer
::
PictureLayer
(
const
SkPoint
&
offset
,
SkiaGPUObject
<
SkPicture
>
picture
,
bool
is_complex
,
bool
will_change
)
:
offset_
(
offset
),
bool
will_change
,
size_t
external_size
)
:
Layer
(
external_size
),
offset_
(
offset
),
picture_
(
std
::
move
(
picture
)),
is_complex_
(
is_complex
),
will_change_
(
will_change
)
{}
...
...
@@ -26,6 +28,7 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
SkPicture
*
sk_picture
=
picture
();
bool
cached
=
false
;
if
(
auto
*
cache
=
context
->
raster_cache
)
{
TRACE_EVENT0
(
"flutter"
,
"PictureLayer::RasterCache (Preroll)"
);
...
...
@@ -34,8 +37,13 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
ctm
=
RasterCache
::
GetIntegralTransCTM
(
ctm
);
#endif
cache
->
Prepare
(
context
->
gr_context
,
sk_picture
,
ctm
,
context
->
dst_color_space
,
is_complex_
,
will_change_
);
cached
=
cache
->
Prepare
(
context
->
gr_context
,
sk_picture
,
ctm
,
context
->
dst_color_space
,
is_complex_
,
will_change_
,
external_size
());
}
if
(
!
cached
)
{
context
->
uncached_external_size
+=
external_size
();
}
SkRect
bounds
=
sk_picture
->
cullRect
().
makeOffset
(
offset_
.
x
(),
offset_
.
y
());
...
...
flow/layers/picture_layer.h
浏览文件 @
3930ac1b
...
...
@@ -18,7 +18,8 @@ class PictureLayer : public Layer {
PictureLayer
(
const
SkPoint
&
offset
,
SkiaGPUObject
<
SkPicture
>
picture
,
bool
is_complex
,
bool
will_change
);
bool
will_change
,
size_t
external_size
);
SkPicture
*
picture
()
const
{
return
picture_
.
get
().
get
();
}
...
...
flow/layers/picture_layer_unittests.cc
浏览文件 @
3930ac1b
...
...
@@ -24,7 +24,7 @@ using PictureLayerTest = SkiaGPUObjectLayerTest;
TEST_F
(
PictureLayerTest
,
PaintBeforePrerollInvalidPictureDies
)
{
const
SkPoint
layer_offset
=
SkPoint
::
Make
(
0.0
f
,
0.0
f
);
auto
layer
=
std
::
make_shared
<
PictureLayer
>
(
layer_offset
,
SkiaGPUObject
<
SkPicture
>
(),
false
,
false
);
layer_offset
,
SkiaGPUObject
<
SkPicture
>
(),
false
,
false
,
0
);
EXPECT_DEATH_IF_SUPPORTED
(
layer
->
Paint
(
paint_context
()),
"picture_
\\
.get
\\
(
\\
)"
);
...
...
@@ -35,7 +35,8 @@ TEST_F(PictureLayerTest, PaintBeforePreollDies) {
const
SkRect
picture_bounds
=
SkRect
::
MakeLTRB
(
5.0
f
,
6.0
f
,
20.5
f
,
21.5
f
);
auto
mock_picture
=
SkPicture
::
MakePlaceholder
(
picture_bounds
);
auto
layer
=
std
::
make_shared
<
PictureLayer
>
(
layer_offset
,
SkiaGPUObject
(
mock_picture
,
unref_queue
()),
false
,
false
);
layer_offset
,
SkiaGPUObject
(
mock_picture
,
unref_queue
()),
false
,
false
,
0
);
EXPECT_EQ
(
layer
->
paint_bounds
(),
SkRect
::
MakeEmpty
());
EXPECT_DEATH_IF_SUPPORTED
(
layer
->
Paint
(
paint_context
()),
...
...
@@ -47,7 +48,8 @@ TEST_F(PictureLayerTest, PaintingEmptyLayerDies) {
const
SkRect
picture_bounds
=
SkRect
::
MakeEmpty
();
auto
mock_picture
=
SkPicture
::
MakePlaceholder
(
picture_bounds
);
auto
layer
=
std
::
make_shared
<
PictureLayer
>
(
layer_offset
,
SkiaGPUObject
(
mock_picture
,
unref_queue
()),
false
,
false
);
layer_offset
,
SkiaGPUObject
(
mock_picture
,
unref_queue
()),
false
,
false
,
0
);
layer
->
Preroll
(
preroll_context
(),
SkMatrix
());
EXPECT_EQ
(
layer
->
paint_bounds
(),
SkRect
::
MakeEmpty
());
...
...
@@ -62,7 +64,7 @@ TEST_F(PictureLayerTest, PaintingEmptyLayerDies) {
TEST_F
(
PictureLayerTest
,
InvalidPictureDies
)
{
const
SkPoint
layer_offset
=
SkPoint
::
Make
(
0.0
f
,
0.0
f
);
auto
layer
=
std
::
make_shared
<
PictureLayer
>
(
layer_offset
,
SkiaGPUObject
<
SkPicture
>
(),
false
,
false
);
layer_offset
,
SkiaGPUObject
<
SkPicture
>
(),
false
,
false
,
0
);
// Crashes reading a nullptr.
EXPECT_DEATH_IF_SUPPORTED
(
layer
->
Preroll
(
preroll_context
(),
SkMatrix
()),
""
);
...
...
@@ -75,7 +77,10 @@ TEST_F(PictureLayerTest, SimplePicture) {
const
SkRect
picture_bounds
=
SkRect
::
MakeLTRB
(
5.0
f
,
6.0
f
,
20.5
f
,
21.5
f
);
auto
mock_picture
=
SkPicture
::
MakePlaceholder
(
picture_bounds
);
auto
layer
=
std
::
make_shared
<
PictureLayer
>
(
layer_offset
,
SkiaGPUObject
(
mock_picture
,
unref_queue
()),
false
,
false
);
layer_offset
,
SkiaGPUObject
(
mock_picture
,
unref_queue
()),
false
,
false
,
1000
);
EXPECT_EQ
(
layer
->
external_size
(),
1000ul
);
layer
->
Preroll
(
preroll_context
(),
SkMatrix
());
EXPECT_EQ
(
layer
->
paint_bounds
(),
...
...
flow/raster_cache.cc
浏览文件 @
3930ac1b
...
...
@@ -141,6 +141,7 @@ void RasterCache::Prepare(PrerollContext* context,
Entry
&
entry
=
layer_cache_
[
cache_key
];
entry
.
access_count
++
;
entry
.
used_this_frame
=
true
;
entry
.
external_size
=
layer
->
external_size
();
if
(
!
entry
.
image
)
{
entry
.
image
=
RasterizeLayer
(
context
,
layer
,
ctm
,
checkerboard_images_
);
}
...
...
@@ -181,7 +182,8 @@ bool RasterCache::Prepare(GrDirectContext* context,
const
SkMatrix
&
transformation_matrix
,
SkColorSpace
*
dst_color_space
,
bool
is_complex
,
bool
will_change
)
{
bool
will_change
,
size_t
external_size
)
{
// Disabling caching when access_threshold is zero is historic behavior.
if
(
access_threshold_
==
0
)
{
return
false
;
...
...
@@ -207,6 +209,7 @@ bool RasterCache::Prepare(GrDirectContext* context,
// Creates an entry, if not present prior.
Entry
&
entry
=
picture_cache_
[
cache_key
];
entry
.
external_size
=
external_size
;
if
(
entry
.
access_count
<
access_threshold_
)
{
// Frame threshold has not yet been reached.
return
false
;
...
...
@@ -260,11 +263,12 @@ bool RasterCache::Draw(const Layer* layer,
return
false
;
}
void
RasterCache
::
SweepAfterFrame
()
{
SweepOneCacheAfterFrame
(
picture_cache_
);
SweepOneCacheAfterFrame
(
layer_cache_
);
size_t
RasterCache
::
SweepAfterFrame
()
{
size_t
removed_size
=
SweepOneCacheAfterFrame
(
picture_cache_
);
removed_size
+=
SweepOneCacheAfterFrame
(
layer_cache_
);
picture_cached_this_frame_
=
0
;
TraceStatsToTimeline
();
return
removed_size
;
}
void
RasterCache
::
Clear
()
{
...
...
flow/raster_cache.h
浏览文件 @
3930ac1b
...
...
@@ -137,7 +137,8 @@ class RasterCache {
const
SkMatrix
&
transformation_matrix
,
SkColorSpace
*
dst_color_space
,
bool
is_complex
,
bool
will_change
);
bool
will_change
,
size_t
external_size
=
0
);
void
Prepare
(
PrerollContext
*
context
,
Layer
*
layer
,
const
SkMatrix
&
ctm
);
...
...
@@ -156,7 +157,8 @@ class RasterCache {
SkCanvas
&
canvas
,
SkPaint
*
paint
=
nullptr
)
const
;
void
SweepAfterFrame
();
/// Returns the amount of external bytes freed by the sweep.
size_t
SweepAfterFrame
();
void
Clear
();
...
...
@@ -192,17 +194,20 @@ class RasterCache {
struct
Entry
{
bool
used_this_frame
=
false
;
size_t
access_count
=
0
;
size_t
external_size
=
0
;
std
::
unique_ptr
<
RasterCacheResult
>
image
;
};
template
<
class
Cache
>
static
void
SweepOneCacheAfterFrame
(
Cache
&
cache
)
{
static
size_t
SweepOneCacheAfterFrame
(
Cache
&
cache
)
{
std
::
vector
<
typename
Cache
::
iterator
>
dead
;
size_t
removed_size
=
0
;
for
(
auto
it
=
cache
.
begin
();
it
!=
cache
.
end
();
++
it
)
{
Entry
&
entry
=
it
->
second
;
if
(
!
entry
.
used_this_frame
)
{
dead
.
push_back
(
it
);
removed_size
+=
entry
.
external_size
;
}
entry
.
used_this_frame
=
false
;
}
...
...
@@ -210,6 +215,7 @@ class RasterCache {
for
(
auto
it
:
dead
)
{
cache
.
erase
(
it
);
}
return
removed_size
;
}
const
size_t
access_threshold_
;
...
...
lib/ui/compositing/scene_builder.cc
浏览文件 @
3930ac1b
...
...
@@ -220,7 +220,7 @@ void SceneBuilder::addPicture(double dx,
pictureRect
.
offset
(
offset
.
x
(),
offset
.
y
());
auto
layer
=
std
::
make_unique
<
flutter
::
PictureLayer
>
(
offset
,
UIDartState
::
CreateGPUObject
(
picture
->
picture
()),
!!
(
hints
&
1
),
!!
(
hints
&
2
));
!!
(
hints
&
2
)
,
picture
->
GetAllocationSize
()
);
AddLayer
(
std
::
move
(
layer
));
}
...
...
lib/ui/fixtures/ui_test.dart
浏览文件 @
3930ac1b
...
...
@@ -3,6 +3,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:typed_data'
;
import
'dart:ui'
;
...
...
@@ -73,3 +74,59 @@ Future<void> encodeImageProducesExternalUint8List() async {
void
_encodeImage
(
Image
i
,
int
format
,
void
Function
(
Uint8List
result
))
native
'EncodeImage'
;
void
_validateExternal
(
Uint8List
result
)
native
'ValidateExternal'
;
@pragma
(
'vm:entry-point'
)
Future
<
void
>
pumpImage
()
async
{
final
FrameCallback
renderBlank
=
(
Duration
duration
)
{
final
PictureRecorder
recorder
=
PictureRecorder
();
final
Canvas
canvas
=
Canvas
(
recorder
);
canvas
.
drawRect
(
Rect
.
largest
,
Paint
());
final
Picture
picture
=
recorder
.
endRecording
();
final
SceneBuilder
builder
=
SceneBuilder
();
builder
.
addPicture
(
Offset
.
zero
,
picture
);
final
Scene
scene
=
builder
.
build
();
window
.
render
(
scene
);
scene
.
dispose
();
window
.
onBeginFrame
=
(
Duration
duration
)
{
window
.
onDrawFrame
=
_onBeginFrameDone
;
};
window
.
scheduleFrame
();
};
final
FrameCallback
renderImage
=
(
Duration
duration
)
{
const
int
width
=
8000
;
const
int
height
=
8000
;
final
Completer
<
Image
>
completer
=
Completer
<
Image
>();
decodeImageFromPixels
(
Uint8List
.
fromList
(
List
<
int
>.
filled
(
width
*
height
*
4
,
0xFF
)),
width
,
height
,
PixelFormat
.
rgba8888
,
(
Image
image
)
=>
completer
.
complete
(
image
),
);
completer
.
future
.
then
((
Image
image
)
{
final
PictureRecorder
recorder
=
PictureRecorder
();
final
Canvas
canvas
=
Canvas
(
recorder
);
canvas
.
drawImage
(
image
,
Offset
.
zero
,
Paint
());
final
Picture
picture
=
recorder
.
endRecording
();
final
SceneBuilder
builder
=
SceneBuilder
();
builder
.
addPicture
(
Offset
.
zero
,
picture
);
_captureImageAndPicture
(
image
,
picture
);
final
Scene
scene
=
builder
.
build
();
window
.
render
(
scene
);
scene
.
dispose
();
window
.
onBeginFrame
=
renderBlank
;
window
.
scheduleFrame
();
});
};
window
.
onBeginFrame
=
renderImage
;
window
.
scheduleFrame
();
}
void
_captureImageAndPicture
(
Image
image
,
Picture
picture
)
native
'CaptureImageAndPicture'
;
Future
<
void
>
_onBeginFrameDone
()
native
'OnBeginFrameDone'
;
runtime/runtime_controller.cc
浏览文件 @
3930ac1b
...
...
@@ -233,7 +233,7 @@ bool RuntimeController::ReportTimings(std::vector<int64_t> timings) {
return
false
;
}
bool
RuntimeController
::
NotifyIdle
(
int64_t
deadline
)
{
bool
RuntimeController
::
NotifyIdle
(
int64_t
deadline
,
size_t
freed_hint
)
{
std
::
shared_ptr
<
DartIsolate
>
root_isolate
=
root_isolate_
.
lock
();
if
(
!
root_isolate
)
{
return
false
;
...
...
@@ -241,6 +241,9 @@ bool RuntimeController::NotifyIdle(int64_t deadline) {
tonic
::
DartState
::
Scope
scope
(
root_isolate
);
// Dart will use the freed hint at the next idle notification. Make sure to
// Update it with our latest value before calling NotifyIdle.
Dart_HintFreed
(
freed_hint
);
Dart_NotifyIdle
(
deadline
);
// Idle notifications being in isolate scope are part of the contract.
...
...
runtime/runtime_controller.h
浏览文件 @
3930ac1b
...
...
@@ -329,9 +329,12 @@ class RuntimeController : public PlatformConfigurationClient {
/// system's monotonic time. The clock can be accessed via
/// `Dart_TimelineGetMicros`.
///
/// @param[in] freed_hint A hint of the number of bytes potentially freed
/// since the last call to NotifyIdle if a GC were run.
///
/// @return If the idle notification was forwarded to the running isolate.
///
bool
NotifyIdle
(
int64_t
deadline
);
bool
NotifyIdle
(
int64_t
deadline
,
size_t
freed_hint
);
//----------------------------------------------------------------------------
/// @brief Returns if the root isolate is running. The isolate must be
...
...
shell/common/engine.cc
浏览文件 @
3930ac1b
...
...
@@ -248,11 +248,16 @@ void Engine::ReportTimings(std::vector<int64_t> timings) {
runtime_controller_
->
ReportTimings
(
std
::
move
(
timings
));
}
void
Engine
::
HintFreed
(
size_t
size
)
{
hint_freed_bytes_since_last_idle_
+=
size
;
}
void
Engine
::
NotifyIdle
(
int64_t
deadline
)
{
auto
trace_event
=
std
::
to_string
(
deadline
-
Dart_TimelineGetMicros
());
TRACE_EVENT1
(
"flutter"
,
"Engine::NotifyIdle"
,
"deadline_now_delta"
,
trace_event
.
c_str
());
runtime_controller_
->
NotifyIdle
(
deadline
);
runtime_controller_
->
NotifyIdle
(
deadline
,
hint_freed_bytes_since_last_idle_
);
hint_freed_bytes_since_last_idle_
=
0
;
}
std
::
pair
<
bool
,
uint32_t
>
Engine
::
GetUIIsolateReturnCode
()
{
...
...
shell/common/engine.h
浏览文件 @
3930ac1b
...
...
@@ -465,6 +465,14 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
///
void
BeginFrame
(
fml
::
TimePoint
frame_time
);
//----------------------------------------------------------------------------
/// @brief Notifies the engine that native bytes might be freed if a
/// garbage collection ran now.
///
/// @param[in] size The number of bytes freed.
///
void
HintFreed
(
size_t
size
);
//----------------------------------------------------------------------------
/// @brief Notifies the engine that the UI task runner is not expected to
/// undertake a new frame workload till a specified timepoint. The
...
...
@@ -797,6 +805,7 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
FontCollection
font_collection_
;
ImageDecoder
image_decoder_
;
TaskRunners
task_runners_
;
size_t
hint_freed_bytes_since_last_idle_
=
0
;
fml
::
WeakPtrFactory
<
Engine
>
weak_factory_
;
// |RuntimeDelegate|
...
...
shell/common/rasterizer.cc
浏览文件 @
3930ac1b
...
...
@@ -27,8 +27,7 @@ static constexpr std::chrono::milliseconds kSkiaCleanupExpiration(15000);
Rasterizer
::
Rasterizer
(
Delegate
&
delegate
)
:
Rasterizer
(
delegate
,
std
::
make_unique
<
flutter
::
CompositorContext
>
(
delegate
.
GetFrameBudget
()))
{}
std
::
make_unique
<
flutter
::
CompositorContext
>
(
delegate
))
{}
Rasterizer
::
Rasterizer
(
Delegate
&
delegate
,
...
...
shell/common/rasterizer.h
浏览文件 @
3930ac1b
...
...
@@ -50,7 +50,7 @@ class Rasterizer final : public SnapshotDelegate {
/// are made on the GPU task runner. Any delegate must ensure that
/// they can handle the threading implications.
///
class
Delegate
{
class
Delegate
:
public
CompositorContext
::
Delegate
{
public:
//--------------------------------------------------------------------------
/// @brief Notifies the delegate that a frame has been rendered. The
...
...
shell/common/shell.cc
浏览文件 @
3930ac1b
...
...
@@ -1179,6 +1179,16 @@ void Shell::OnFrameRasterized(const FrameTiming& timing) {
}
}
void
Shell
::
OnCompositorEndFrame
(
size_t
freed_hint
)
{
FML_DCHECK
(
task_runners_
.
GetRasterTaskRunner
()
->
RunsTasksOnCurrentThread
());
task_runners_
.
GetUITaskRunner
()
->
PostTask
(
[
engine
=
weak_engine_
,
freed_hint
=
freed_hint
]()
{
if
(
engine
)
{
engine
->
HintFreed
(
freed_hint
);
}
});
}
fml
::
Milliseconds
Shell
::
GetFrameBudget
()
{
if
(
display_refresh_rate_
>
0
)
{
return
fml
::
RefreshRateToFrameBudget
(
display_refresh_rate_
.
load
());
...
...
shell/common/shell.h
浏览文件 @
3930ac1b
...
...
@@ -12,6 +12,7 @@
#include "flutter/common/settings.h"
#include "flutter/common/task_runners.h"
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/surface.h"
#include "flutter/flow/texture.h"
#include "flutter/fml/closure.h"
...
...
@@ -528,10 +529,14 @@ class Shell final : public PlatformView::Delegate,
void
OnFrameRasterized
(
const
FrameTiming
&
)
override
;
// |Rasterizer::Delegate|
fml
::
Milliseconds
GetFrameBudget
()
override
;
fml
::
TimePoint
GetLatestFrameTargetTime
()
const
override
;
// |Rasterizer::Delegate|
fml
::
TimePoint
GetLatestFrameTargetTime
()
const
override
;
// |CompositorContext::Delegate|
fml
::
Milliseconds
GetFrameBudget
()
override
;
// |CompositorContext::Delegate|
void
OnCompositorEndFrame
(
size_t
freed_hint
)
override
;
// |ServiceProtocol::Handler|
fml
::
RefPtr
<
fml
::
TaskRunner
>
GetServiceProtocolHandlerTaskRunner
(
...
...
shell/common/shell_test.cc
浏览文件 @
3930ac1b
...
...
@@ -106,6 +106,40 @@ void ShellTest::VSyncFlush(Shell* shell, bool& will_draw_new_frame) {
latch
.
Wait
();
}
void
ShellTest
::
SetViewportMetrics
(
Shell
*
shell
,
double
width
,
double
height
)
{
flutter
::
ViewportMetrics
viewport_metrics
=
{
1
,
// device pixel ratio
width
,
// physical width
height
,
// physical height
0
,
// padding top
0
,
// padding right
0
,
// padding bottom
0
,
// padding left
0
,
// view inset top
0
,
// view inset right
0
,
// view inset bottom
0
,
// view inset left
0
,
// gesture inset top
0
,
// gesture inset right
0
,
// gesture inset bottom
0
// gesture inset left
};
// Set viewport to nonempty, and call Animator::BeginFrame to make the layer
// tree pipeline nonempty. Without either of this, the layer tree below
// won't be rasterized.
fml
::
AutoResetWaitableEvent
latch
;
shell
->
GetTaskRunners
().
GetUITaskRunner
()
->
PostTask
(
[
&
latch
,
engine
=
shell
->
weak_engine_
,
viewport_metrics
]()
{
engine
->
SetViewportMetrics
(
std
::
move
(
viewport_metrics
));
const
auto
frame_begin_time
=
fml
::
TimePoint
::
Now
();
const
auto
frame_end_time
=
frame_begin_time
+
fml
::
TimeDelta
::
FromSecondsF
(
1.0
/
60.0
);
engine
->
animator_
->
BeginFrame
(
frame_begin_time
,
frame_end_time
);
latch
.
Signal
();
});
latch
.
Wait
();
}
void
ShellTest
::
PumpOneFrame
(
Shell
*
shell
,
double
width
,
double
height
,
...
...
shell/common/shell_test.h
浏览文件 @
3930ac1b
...
...
@@ -59,6 +59,7 @@ class ShellTest : public FixtureTest {
/// the `will_draw_new_frame` to true.
static
void
VSyncFlush
(
Shell
*
shell
,
bool
&
will_draw_new_frame
);
static
void
SetViewportMetrics
(
Shell
*
shell
,
double
width
,
double
height
);
/// Given the root layer, this callback builds the layer tree to be rasterized
/// in PumpOneFrame.
using
LayerTreeBuilder
=
...
...
shell/common/shell_unittests.cc
浏览文件 @
3930ac1b
...
...
@@ -536,7 +536,8 @@ TEST_F(ShellTest, ExternalEmbedderNoThreadMerger) {
this
->
GetCurrentTaskRunner
(),
fml
::
TimeDelta
::
FromSeconds
(
0
));
auto
picture_layer
=
std
::
make_shared
<
PictureLayer
>
(
SkPoint
::
Make
(
10
,
10
),
flutter
::
SkiaGPUObject
<
SkPicture
>
({
sk_picture
,
queue
}),
false
,
false
);
flutter
::
SkiaGPUObject
<
SkPicture
>
({
sk_picture
,
queue
}),
false
,
false
,
0
);
root
->
Add
(
picture_layer
);
};
...
...
@@ -585,7 +586,8 @@ TEST_F(ShellTest,
this
->
GetCurrentTaskRunner
(),
fml
::
TimeDelta
::
FromSeconds
(
0
));
auto
picture_layer
=
std
::
make_shared
<
PictureLayer
>
(
SkPoint
::
Make
(
10
,
10
),
flutter
::
SkiaGPUObject
<
SkPicture
>
({
sk_picture
,
queue
}),
false
,
false
);
flutter
::
SkiaGPUObject
<
SkPicture
>
({
sk_picture
,
queue
}),
false
,
false
,
0
);
root
->
Add
(
picture_layer
);
};
...
...
@@ -1460,7 +1462,8 @@ TEST_F(ShellTest, Screenshot) {
this
->
GetCurrentTaskRunner
(),
fml
::
TimeDelta
::
FromSeconds
(
0
));
auto
picture_layer
=
std
::
make_shared
<
PictureLayer
>
(
SkPoint
::
Make
(
10
,
10
),
flutter
::
SkiaGPUObject
<
SkPicture
>
({
sk_picture
,
queue
}),
false
,
false
);
flutter
::
SkiaGPUObject
<
SkPicture
>
({
sk_picture
,
queue
}),
false
,
false
,
0
);
root
->
Add
(
picture_layer
);
};
...
...
@@ -1746,7 +1749,7 @@ TEST_F(ShellTest, OnServiceProtocolEstimateRasterCacheMemoryWorks) {
auto
picture_layer
=
std
::
make_shared
<
PictureLayer
>
(
SkPoint
::
Make
(
0
,
0
),
flutter
::
SkiaGPUObject
<
SkPicture
>
({
MakeSizedPicture
(
100
,
100
),
queue
}),
false
,
false
);
false
,
false
,
0
);
picture_layer
->
set_paint_bounds
(
SkRect
::
MakeWH
(
100
,
100
));
// 2. Rasterize the picture and the picture layer in the raster cache.
...
...
shell/common/skp_shader_warmup_unittests.cc
浏览文件 @
3930ac1b
...
...
@@ -153,7 +153,8 @@ class SkpWarmupTest : public ShellTest {
auto
picture_layer
=
std
::
make_shared
<
PictureLayer
>
(
SkPoint
::
Make
(
0
,
0
),
SkiaGPUObject
<
SkPicture
>
(
picture
,
queue
),
/* is_complex */
false
,
/* will_change */
false
);
/* will_change */
false
,
/* external_size */
0
);
root
->
Add
(
picture_layer
);
};
PumpOneFrame
(
shell
.
get
(),
picture
->
cullRect
().
width
(),
...
...
@@ -235,7 +236,8 @@ TEST_F(SkpWarmupTest, Image) {
auto
picture_layer
=
std
::
make_shared
<
PictureLayer
>
(
SkPoint
::
Make
(
0
,
0
),
SkiaGPUObject
<
SkPicture
>
(
picture
,
queue
),
/* is_complex */
false
,
/* will_change */
false
);
/* will_change */
false
,
/* external_size */
0
);
root
->
Add
(
picture_layer
);
};
...
...
shell/platform/fuchsia/flutter/compositor_context.cc
浏览文件 @
3930ac1b
...
...
@@ -140,10 +140,12 @@ class ScopedFrame final : public flutter::CompositorContext::ScopedFrame {
};
CompositorContext
::
CompositorContext
(
flutter
::
CompositorContext
::
Delegate
&
delegate
,
SessionConnection
&
session_connection
,
VulkanSurfaceProducer
&
surface_producer
,
flutter
::
SceneUpdateContext
&
scene_update_context
)
:
session_connection_
(
session_connection
),
:
flutter
::
CompositorContext
(
delegate
),
session_connection_
(
session_connection
),
surface_producer_
(
surface_producer
),
scene_update_context_
(
scene_update_context
)
{}
...
...
shell/platform/fuchsia/flutter/compositor_context.h
浏览文件 @
3930ac1b
...
...
@@ -21,7 +21,8 @@ namespace flutter_runner {
// Fuchsia.
class
CompositorContext
final
:
public
flutter
::
CompositorContext
{
public:
CompositorContext
(
SessionConnection
&
session_connection
,
CompositorContext
(
CompositorContext
::
Delegate
&
delegate
,
SessionConnection
&
session_connection
,
VulkanSurfaceProducer
&
surface_producer
,
flutter
::
SceneUpdateContext
&
scene_update_context
);
...
...
shell/platform/fuchsia/flutter/engine.cc
浏览文件 @
3930ac1b
...
...
@@ -216,7 +216,7 @@ Engine::Engine(Delegate& delegate,
std
::
unique_ptr
<
flutter_runner
::
CompositorContext
>
compositor_context
=
std
::
make_unique
<
flutter_runner
::
CompositorContext
>
(
session_connection_
.
value
(),
surface_producer_
.
value
(),
s
hell
,
s
ession_connection_
.
value
(),
surface_producer_
.
value
(),
scene_update_context_
.
value
());
return
std
::
make_unique
<
flutter
::
Rasterizer
>
(
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录