Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43355755
engine
提交
8973c733
E
engine
项目概览
weixin_43355755
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
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,发现更多精彩内容 >>
未验证
提交
8973c733
编写于
4月 18, 2018
作者:
C
Chinmay Garde
提交者:
GitHub
4月 18, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement Scene::toImage for creating a raster image representation of a scene. (#5021)
上级
572c5844
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
196 addition
and
4 deletion
+196
-4
flow/layers/layer_tree.cc
flow/layers/layer_tree.cc
+43
-1
flow/layers/layer_tree.h
flow/layers/layer_tree.h
+3
-0
lib/ui/compositing.dart
lib/ui/compositing.dart
+13
-0
lib/ui/compositing/scene.cc
lib/ui/compositing/scene.cc
+133
-3
lib/ui/compositing/scene.h
lib/ui/compositing/scene.h
+4
-0
未找到文件。
flow/layers/layer_tree.cc
浏览文件 @
8973c733
...
...
@@ -6,6 +6,7 @@
#include "flutter/flow/layers/layer.h"
#include "flutter/glue/trace_event.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
namespace
flow
{
...
...
@@ -60,6 +61,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
#endif
void
LayerTree
::
Paint
(
CompositorContext
::
ScopedFrame
&
frame
)
const
{
TRACE_EVENT0
(
"flutter"
,
"LayerTree::Paint"
);
Layer
::
PaintContext
context
=
{
*
frame
.
canvas
(),
//
frame
.
context
().
frame_time
(),
//
...
...
@@ -67,10 +69,50 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame) const {
frame
.
context
().
texture_registry
(),
//
checkerboard_offscreen_layers_
//
};
TRACE_EVENT0
(
"flutter"
,
"LayerTree::Paint"
);
if
(
root_layer_
->
needs_painting
())
root_layer_
->
Paint
(
context
);
}
sk_sp
<
SkPicture
>
LayerTree
::
Flatten
(
const
SkRect
&
bounds
)
{
TRACE_EVENT0
(
"flutter"
,
"LayerTree::Flatten"
);
SkPictureRecorder
recorder
;
auto
canvas
=
recorder
.
beginRecording
(
bounds
);
if
(
!
canvas
)
{
return
nullptr
;
}
Layer
::
PrerollContext
preroll_context
{
nullptr
,
// raster_cache (don't consult the cache)
nullptr
,
// gr_context (used for the raster cache)
nullptr
,
// SkColorSpace* dst_color_space
SkRect
::
MakeEmpty
(),
// SkRect child_paint_bounds
};
const
Stopwatch
unused_stopwatch
;
TextureRegistry
unused_texture_registry
;
Layer
::
PaintContext
paint_context
=
{
*
canvas
,
// canvas
unused_stopwatch
,
// frame time (dont care)
unused_stopwatch
,
// engine time (dont care)
unused_texture_registry
,
// texture registry (not supported)
false
// checkerboard offscreen layers
};
// Even if we don't have a root layer, we still need to create an empty
// picture.
if
(
root_layer_
)
{
root_layer_
->
Preroll
(
&
preroll_context
,
SkMatrix
::
I
());
// The needs painting flag may be set after the preroll. So check it after.
if
(
root_layer_
->
needs_painting
())
{
root_layer_
->
Paint
(
paint_context
);
}
}
return
recorder
.
finishRecordingAsPicture
();
}
}
// namespace flow
flow/layers/layer_tree.h
浏览文件 @
8973c733
...
...
@@ -13,6 +13,7 @@
#include "flutter/flow/layers/layer.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/time/time_delta.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkSize.h"
namespace
flow
{
...
...
@@ -33,6 +34,8 @@ class LayerTree {
void
Paint
(
CompositorContext
::
ScopedFrame
&
frame
)
const
;
sk_sp
<
SkPicture
>
Flatten
(
const
SkRect
&
bounds
);
Layer
*
root_layer
()
const
{
return
root_layer_
.
get
();
}
void
set_root_layer
(
std
::
unique_ptr
<
Layer
>
root_layer
)
{
...
...
lib/ui/compositing.dart
浏览文件 @
8973c733
...
...
@@ -17,6 +17,19 @@ class Scene extends NativeFieldWrapperClass2 {
/// To create a Scene object, use a [SceneBuilder].
Scene
.
_
();
/// Creates a raster image representation of the current state of the scene.
/// This is a slow operation that is performed on a background thread.
Future
<
Image
>
toImage
(
int
width
,
int
height
)
{
if
(
width
<=
0
||
height
<=
0
)
throw
new
Exception
(
'Invalid image dimensions.'
);
return
_futurize
(
(
_Callback
<
Image
>
callback
)
=>
_toImage
(
width
,
height
,
callback
)
);
}
String
_toImage
(
int
width
,
int
height
,
_Callback
<
Image
>
callback
)
native
'Scene_toImage'
;
/// Releases the resources used by this scene.
///
/// After calling this function, the scene is cannot be used further.
...
...
lib/ui/compositing/scene.cc
浏览文件 @
8973c733
...
...
@@ -4,18 +4,26 @@
#include "flutter/lib/ui/compositing/scene.h"
#include "flutter/fml/trace_event.h"
#include "flutter/lib/ui/painting/image.h"
#include "lib/fxl/functional/make_copyable.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_args.h"
#include "lib/tonic/dart_binding_macros.h"
#include "lib/tonic/dart_library_natives.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "lib/tonic/dart_persistent_value.h"
#include "lib/tonic/dart_wrappable.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace
blink
{
IMPLEMENT_WRAPPERTYPEINFO
(
ui
,
Scene
);
#define FOR_EACH_BINDING(V) V(Scene, dispose)
#define FOR_EACH_BINDING(V) \
V(Scene, toImage) \
V(Scene, dispose)
DART_BIND_ALL
(
Scene
,
FOR_EACH_BINDING
)
...
...
@@ -46,6 +54,128 @@ void Scene::dispose() {
ClearDartWrapper
();
}
static
sk_sp
<
SkImage
>
CreateSceneSnapshot
(
GrContext
*
context
,
sk_sp
<
SkPicture
>
picture
,
const
SkSize
&
size
)
{
TRACE_EVENT0
(
"flutter"
,
"CreateSceneSnapshot"
);
auto
image_info
=
SkImageInfo
::
MakeN32Premul
(
SkISize
::
Make
(
size
.
width
(),
size
.
height
()));
sk_sp
<
SkSurface
>
surface
;
if
(
context
)
{
surface
=
SkSurface
::
MakeRenderTarget
(
context
,
SkBudgeted
::
kNo
,
image_info
);
}
if
(
!
surface
)
{
surface
=
SkSurface
::
MakeRaster
(
image_info
);
}
if
(
!
surface
)
{
return
nullptr
;
}
auto
canvas
=
surface
->
getCanvas
();
if
(
!
canvas
)
{
return
nullptr
;
}
if
(
picture
)
{
canvas
->
drawPicture
(
picture
.
get
());
}
auto
snapshot
=
surface
->
makeImageSnapshot
();
if
(
!
snapshot
)
{
return
nullptr
;
}
return
snapshot
->
makeRasterImage
();
}
Dart_Handle
Scene
::
toImage
(
uint32_t
width
,
uint32_t
height
,
Dart_Handle
raw_image_callback
)
{
TRACE_EVENT0
(
"flutter"
,
"Scene::toImage"
);
if
(
Dart_IsNull
(
raw_image_callback
)
||
!
Dart_IsClosure
(
raw_image_callback
))
{
return
tonic
::
ToDart
(
"Image callback was invalid"
);
}
if
(
!
m_layerTree
)
{
return
tonic
::
ToDart
(
"Scene did not contain a layer tree."
);
}
if
(
width
==
0
||
height
==
0
)
{
return
tonic
::
ToDart
(
"Image dimensions for scene were invalid."
);
}
auto
dart_state
=
UIDartState
::
Current
();
auto
image_callback
=
std
::
make_unique
<
tonic
::
DartPersistentValue
>
(
dart_state
,
raw_image_callback
);
// We can't create an image on this task runner because we don't have a
// graphics context. Even if we did, it would be slow anyway. Also, this
// thread owns the sole reference to the layer tree. So we flatten the layer
// tree into a picture and use that as the thread transport mechanism.
auto
bounds_size
=
SkSize
::
Make
(
width
,
height
);
auto
picture
=
m_layerTree
->
Flatten
(
SkRect
::
MakeSize
(
bounds_size
));
if
(
!
picture
)
{
// Already in Dart scope.
return
tonic
::
ToDart
(
"Could not flatten scene into a layer tree."
);
}
auto
resource_context
=
dart_state
->
GetResourceContext
();
auto
ui_task_runner
=
dart_state
->
GetTaskRunners
().
GetUITaskRunner
();
auto
unref_queue
=
dart_state
->
GetSkiaUnrefQueue
();
// The picture has been prepared on the UI thread.
dart_state
->
GetTaskRunners
().
GetIOTaskRunner
()
->
PostTask
(
fxl
::
MakeCopyable
([
picture
=
std
::
move
(
picture
),
//
bounds_size
,
//
resource_context
=
std
::
move
(
resource_context
),
//
ui_task_runner
=
std
::
move
(
ui_task_runner
),
//
image_callback
=
std
::
move
(
image_callback
),
//
unref_queue
=
std
::
move
(
unref_queue
)
//
]()
mutable
{
// Snapshot the picture on the IO thread that contains an optional
// GrContext.
auto
image
=
CreateSceneSnapshot
(
resource_context
.
get
(),
std
::
move
(
picture
),
bounds_size
);
// Send the image back to the UI thread for submission back to the
// framework.
ui_task_runner
->
PostTask
(
fxl
::
MakeCopyable
([
image
=
std
::
move
(
image
),
//
image_callback
=
std
::
move
(
image_callback
),
//
unref_queue
=
std
::
move
(
unref_queue
)
//
]()
mutable
{
auto
dart_state
=
image_callback
->
dart_state
().
get
();
if
(
!
dart_state
)
{
// The root isolate could have died in the meantime.
return
;
}
tonic
::
DartState
::
Scope
scope
(
dart_state
);
if
(
!
image
)
{
tonic
::
DartInvoke
(
image_callback
->
Get
(),
{
Dart_Null
()});
return
;
}
auto
dart_image
=
CanvasImage
::
Create
();
dart_image
->
set_image
({
std
::
move
(
image
),
std
::
move
(
unref_queue
)});
auto
raw_dart_image
=
tonic
::
ToDart
(
std
::
move
(
dart_image
));
// All done!
tonic
::
DartInvoke
(
image_callback
->
Get
(),
{
raw_dart_image
});
}));
}));
return
Dart_Null
();
}
std
::
unique_ptr
<
flow
::
LayerTree
>
Scene
::
takeLayerTree
()
{
return
std
::
move
(
m_layerTree
);
}
...
...
lib/ui/compositing/scene.h
浏览文件 @
8973c733
...
...
@@ -32,6 +32,10 @@ class Scene : public fxl::RefCountedThreadSafe<Scene>,
std
::
unique_ptr
<
flow
::
LayerTree
>
takeLayerTree
();
Dart_Handle
toImage
(
uint32_t
width
,
uint32_t
height
,
Dart_Handle
image_callback
);
void
dispose
();
static
void
RegisterNatives
(
tonic
::
DartLibraryNatives
*
natives
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录