From 71dd5511018025e20f7a80af658a88430b0a7bf0 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 5 Jan 2023 13:29:47 -0800 Subject: [PATCH 01/24] [Impeller Scene] Add scene displaylist op --- display_list/display_list.h | 1 + display_list/display_list_builder.cc | 7 +++ display_list/display_list_color_source.h | 46 +++++++++++++++++++ display_list/display_list_ops.h | 18 ++++++++ .../display_list/display_list_dispatcher.cc | 16 ++++--- 5 files changed, 81 insertions(+), 7 deletions(-) diff --git a/display_list/display_list.h b/display_list/display_list.h index 0fa5636f372cd..8d26950826322 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -91,6 +91,7 @@ namespace flutter { V(SetSkColorSource) \ V(SetImageColorSource) \ V(SetRuntimeEffectColorSource) \ + V(SetSceneColorSource) \ \ V(ClearImageFilter) \ V(SetPodImageFilter) \ diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index b5b1c0e2b9e0e..0d7669954abcd 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -9,6 +9,7 @@ #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/display_list/display_list_color_source.h" #include "flutter/display_list/display_list_ops.h" +#include "fml/logging.h" namespace flutter { @@ -202,6 +203,12 @@ void DisplayListBuilder::onSetColorSource(const DlColorSource* source) { Push(0, 0, effect); break; } + case DlColorSourceType::kScene: { + const DlSceneColorSource* scene = source->asScene(); + FML_DCHECK(scene); + Push(0, 0, scene); + break; + } case DlColorSourceType::kUnknown: Push(0, 0, source->skia_object()); break; diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index 1e5f545554a72..4c4bb77aea131 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -18,6 +18,8 @@ #include "flutter/display_list/display_list_tile_mode.h" #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" +#include "impeller/geometry/matrix.h" +#include "impeller/scene/animation/property_resolver.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkRuntimeEffect.h" @@ -31,6 +33,7 @@ class DlRadialGradientColorSource; class DlConicalGradientColorSource; class DlSweepGradientColorSource; class DlRuntimeEffectColorSource; +class DlSceneColorSource; class DlUnknownColorSource; // The DisplayList ColorSource class. This class implements all of the @@ -51,6 +54,7 @@ enum class DlColorSourceType { kConicalGradient, kSweepGradient, kRuntimeEffect, + kScene, kUnknown }; @@ -160,6 +164,8 @@ class DlColorSource return nullptr; } + virtual const DlSceneColorSource* asScene() const { return nullptr; } + // If this filter contains images, specifies the owning context for those // images. // Images with a DlImage::OwningContext::kRaster must only call skia_object @@ -754,6 +760,46 @@ class DlRuntimeEffectColorSource final : public DlColorSource { FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlRuntimeEffectColorSource); }; +class DlSceneColorSource final : public DlColorSource { + public: + DlSceneColorSource(std::shared_ptr node, + impeller::Matrix camera_matrix) + : node_(std::move(node)), camera_matrix_(camera_matrix) {} + + const DlSceneColorSource* asScene() const override { return this; } + + std::shared_ptr shared() const override { + return std::make_shared(node_, camera_matrix_); + } + + DlColorSourceType type() const override { return DlColorSourceType::kScene; } + size_t size() const override { return sizeof(*this); } + + bool is_opaque() const override { return false; } + + std::shared_ptr scene_node() const { return node_; } + + impeller::Matrix camera_matrix() const { return camera_matrix_; } + + sk_sp skia_object() const override { return nullptr; } + + protected: + bool equals_(DlColorSource const& other) const override { + FML_DCHECK(other.type() == DlColorSourceType::kScene); + auto that = static_cast(&other); + if (node_ != that->node_) { + return false; + } + return true; + } + + private: + std::shared_ptr node_; + impeller::Matrix camera_matrix_; // the view-projection matrix of the scene. + + FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlSceneColorSource); +}; + class DlUnknownColorSource final : public DlColorSource { public: DlUnknownColorSource(sk_sp shader) diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h index 40775cdae7066..d147caafc2659 100644 --- a/display_list/display_list_ops.h +++ b/display_list/display_list_ops.h @@ -312,6 +312,24 @@ struct SetRuntimeEffectColorSourceOp : DLOp { } }; +struct SetSceneColorSourceOp : DLOp { + static const auto kType = DisplayListOpType::kSetSceneColorSource; + + SetSceneColorSourceOp(const DlSceneColorSource* source) + : source(source->scene_node(), source->camera_matrix()) {} + + const DlSceneColorSource source; + + void dispatch(DispatchContext& ctx) const { + ctx.dispatcher.setColorSource(&source); + } + + DisplayListCompare equals(const SetSceneColorSourceOp* other) const { + return (source == other->source) ? DisplayListCompare::kEqual + : DisplayListCompare::kNotEqual; + } +}; + // 4 byte header + 16 byte payload uses 24 total bytes (4 bytes unused) struct SetSharedImageFilterOp : DLOp { static const auto kType = DisplayListOpType::kSetSharedImageFilter; diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 538eff84f1b80..891f37768cb47 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -337,6 +337,8 @@ static std::optional ToColorSourceType( return Paint::ColorSourceType::kSweepGradient; case flutter::DlColorSourceType::kRuntimeEffect: return Paint::ColorSourceType::kRuntimeEffect; + case flutter::DlColorSourceType::kScene: + return Paint::ColorSourceType::kScene; case flutter::DlColorSourceType::kUnknown: return std::nullopt; } @@ -502,15 +504,15 @@ void DisplayListDispatcher::setColorSource( return; } case Paint::ColorSourceType::kScene: { - // const flutter::DlSceneColorSource* scene_color_source = - // source->asScene(); std::shared_ptr scene_node = - // scene_color_source->node(); Matrix camera_transform = - // scene_color_node->camera_transform(); + const flutter::DlSceneColorSource* scene_color_source = source->asScene(); + std::shared_ptr scene_node = + scene_color_source->scene_node(); + Matrix camera_transform = scene_color_source->camera_matrix(); - paint_.color_source = [/*scene_node, camera_transform*/]() { + paint_.color_source = [scene_node, camera_transform]() { auto contents = std::make_shared(); - // contents->SetNode(scene_node); - // contents->SetCameraTransform(camera_transform); + contents->SetNode(scene_node); + contents->SetCameraTransform(camera_transform); return contents; }; } From 5b2f82e16b4fe660bc06a2f9c5b1d507ec6daf70 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 6 Jan 2023 03:50:04 -0800 Subject: [PATCH 02/24] Add dart bindings for scenes --- ci/licenses_golden/licenses_flutter | 12 +- display_list/BUILD.gn | 1 + display_list/display_list_color_source.h | 2 +- lib/ui/BUILD.gn | 5 + lib/ui/compositing/scene_builder.cc | 16 --- lib/ui/compositing/scene_builder.h | 9 -- lib/ui/dart_ui.cc | 20 +++- lib/ui/experiments/compositing_3d.dart | 18 --- lib/ui/experiments/scene.dart | 142 +++++++++++++++++++++++ lib/ui/experiments/ui.dart | 2 +- lib/ui/painting/fragment_program.h | 1 - lib/ui/painting/scene/scene_node.cc | 109 +++++++++++++++++ lib/ui/painting/scene/scene_node.h | 67 +++++++++++ lib/ui/painting/scene/scene_shader.cc | 82 +++++++++++++ lib/ui/painting/scene/scene_shader.h | 45 +++++++ 15 files changed, 481 insertions(+), 50 deletions(-) delete mode 100644 lib/ui/experiments/compositing_3d.dart create mode 100644 lib/ui/experiments/scene.dart create mode 100644 lib/ui/painting/scene/scene_node.cc create mode 100644 lib/ui/painting/scene/scene_node.h create mode 100644 lib/ui/painting/scene/scene_shader.cc create mode 100644 lib/ui/painting/scene/scene_shader.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 02e8ce98e055c..93d013ea75816 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1703,7 +1703,7 @@ ORIGIN: ../../../flutter/lib/ui/dart_runtime_hooks.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/dart_ui.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/dart_ui.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/dart_wrapper.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/lib/ui/experiments/compositing_3d.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/experiments/scene.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/experiments/ui.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/geometry.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/hash_codes.dart + ../../../flutter/LICENSE @@ -1783,6 +1783,10 @@ ORIGIN: ../../../flutter/lib/ui/painting/picture_recorder.cc + ../../../flutter/ ORIGIN: ../../../flutter/lib/ui/painting/picture_recorder.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/painting/rrect.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/painting/rrect.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/painting/scene/scene_node.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/painting/scene/scene_node.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/painting/scene/scene_shader.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/painting/scene/scene_shader.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/painting/shader.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/painting/shader.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/painting/single_frame_codec.cc + ../../../flutter/LICENSE @@ -4175,7 +4179,7 @@ FILE: ../../../flutter/lib/ui/dart_runtime_hooks.h FILE: ../../../flutter/lib/ui/dart_ui.cc FILE: ../../../flutter/lib/ui/dart_ui.h FILE: ../../../flutter/lib/ui/dart_wrapper.h -FILE: ../../../flutter/lib/ui/experiments/compositing_3d.dart +FILE: ../../../flutter/lib/ui/experiments/scene.dart FILE: ../../../flutter/lib/ui/experiments/ui.dart FILE: ../../../flutter/lib/ui/geometry.dart FILE: ../../../flutter/lib/ui/hash_codes.dart @@ -4255,6 +4259,10 @@ FILE: ../../../flutter/lib/ui/painting/picture_recorder.cc FILE: ../../../flutter/lib/ui/painting/picture_recorder.h FILE: ../../../flutter/lib/ui/painting/rrect.cc FILE: ../../../flutter/lib/ui/painting/rrect.h +FILE: ../../../flutter/lib/ui/painting/scene/scene_node.cc +FILE: ../../../flutter/lib/ui/painting/scene/scene_node.h +FILE: ../../../flutter/lib/ui/painting/scene/scene_shader.cc +FILE: ../../../flutter/lib/ui/painting/scene/scene_shader.h FILE: ../../../flutter/lib/ui/painting/shader.cc FILE: ../../../flutter/lib/ui/painting/shader.h FILE: ../../../flutter/lib/ui/painting/single_frame_codec.cc diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 2c9863a6cf907..0cf553b355ad2 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -69,6 +69,7 @@ source_set("display_list") { public_deps = [ "//flutter/fml", "//flutter/impeller/runtime_stage", + "//flutter/impeller/scene", "//third_party/skia", ] } diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index 4c4bb77aea131..4ac78a3b2b632 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -19,7 +19,7 @@ #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" #include "impeller/geometry/matrix.h" -#include "impeller/scene/animation/property_resolver.h" +#include "impeller/scene/node.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkRuntimeEffect.h" diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 9048897a15ff1..c84e8dbd62ae8 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -81,6 +81,10 @@ source_set("ui") { "painting/picture_recorder.h", "painting/rrect.cc", "painting/rrect.h", + "painting/scene/scene_node.cc", + "painting/scene/scene_node.h", + "painting/scene/scene_shader.cc", + "painting/scene/scene_shader.h", "painting/shader.cc", "painting/shader.h", "painting/single_frame_codec.cc", @@ -155,6 +159,7 @@ source_set("ui") { "//flutter/display_list", "//flutter/fml", "//flutter/impeller/runtime_stage", + "//flutter/impeller/scene", "//flutter/runtime:dart_plugin_registrant", "//flutter/runtime:test_font", "//flutter/third_party/tonic", diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index deba7695f4fb7..6f1c718fa1b5f 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -262,22 +262,6 @@ void SceneBuilder::addTexture(double dx, AddLayer(std::move(layer)); } -#ifdef IMPELLER_ENABLE_3D -// static -void SceneBuilder::addModelLayer(Dart_Handle wrapper, - double dx, - double dy, - double width, - double height, - int64_t viewId) { - auto* scene_builder = tonic::DartConverter::FromDart(wrapper); - SkMatrix sk_matrix = SkMatrix::Translate(dx, dy); - auto layer = std::make_shared(sk_matrix); - scene_builder->AddLayer(std::move(layer)); -} - -#endif // IMPELLER_ENABLE_3D - void SceneBuilder::addPlatformView(double dx, double dy, double width, diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index 04d350236dabb..f2de29c4802d2 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -34,15 +34,6 @@ class SceneBuilder : public RefCountedDartWrappable { res->AssociateWithDartWrapper(wrapper); } -#ifdef IMPELLER_ENABLE_3D - static void addModelLayer(Dart_Handle wrapper, - double dx, - double dy, - double width, - double height, - int64_t viewId); -#endif // IMPELLER_ENABLE_3D - ~SceneBuilder() override; void pushTransformHandle(Dart_Handle layer_handle, diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index 4d1a6bca3ac0d..aa7ecb832df12 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -29,6 +29,8 @@ #include "flutter/lib/ui/painting/path_measure.h" #include "flutter/lib/ui/painting/picture.h" #include "flutter/lib/ui/painting/picture_recorder.h" +#include "flutter/lib/ui/painting/scene/scene_node.h" +#include "flutter/lib/ui/painting/scene/scene_shader.h" #include "flutter/lib/ui/painting/vertices.h" #include "flutter/lib/ui/semantics/semantics_update.h" #include "flutter/lib/ui/semantics/semantics_update_builder.h" @@ -295,7 +297,20 @@ typedef CanvasPath Path; V(Vertices, dispose, 1) #ifdef IMPELLER_ENABLE_3D -#define FFI_METHOD_LIST_3D(V) V(SceneBuilder::addModelLayer, 7) + +#define FFI_FUNCTION_LIST_3D(V) \ + V(SceneNode::Create, 1) V(SceneShader::Create, 1) + +#define FFI_METHOD_LIST_3D(V) \ + V(SceneNode, initFromAsset, 3) \ + V(SceneNode, initFromTransform, 2) \ + V(SceneNode, AddChild, 2) \ + V(SceneNode, SetTransform, 2) \ + V(SceneNode, SetAnimationState, 5) \ + V(SceneNode, SeekAnimation, 3) \ + V(SceneShader, SetCameraTransform, 2) \ + V(SceneShader, Dispose, 1) + #endif // IMPELLER_ENABLE_3D #define FFI_FUNCTION_INSERT(FUNCTION, ARGS) \ @@ -325,7 +340,8 @@ void InitDispatcherMap() { FFI_FUNCTION_LIST(FFI_FUNCTION_INSERT) FFI_METHOD_LIST(FFI_METHOD_INSERT) #ifdef IMPELLER_ENABLE_3D - FFI_METHOD_LIST_3D(FFI_FUNCTION_INSERT) + FFI_FUNCTION_LIST_3D(FFI_FUNCTION_INSERT) + FFI_METHOD_LIST_3D(FFI_METHOD_INSERT) #endif // IMPELLER_ENABLE_3D } diff --git a/lib/ui/experiments/compositing_3d.dart b/lib/ui/experiments/compositing_3d.dart deleted file mode 100644 index 3fce6a31e7844..0000000000000 --- a/lib/ui/experiments/compositing_3d.dart +++ /dev/null @@ -1,18 +0,0 @@ -// 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. -part of dart.ui; - -void addModelLayer( - SceneBuilder builder, - int viewId, { - Offset offset = Offset.zero, - double width = 0.0, - double height = 0.0, -}) { - assert(offset != null, 'Offset argument was null'); - _addModelLayer(builder, offset.dx, offset.dy, width, height, viewId); -} - -@FfiNative('SceneBuilder::addModelLayer') -external void _addModelLayer(Object object, double dx, double dy, double width, double height, int viewId); diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart new file mode 100644 index 0000000000000..7a38d37d8168d --- /dev/null +++ b/lib/ui/experiments/scene.dart @@ -0,0 +1,142 @@ +// 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. +part of dart.ui; + +/// A composable [SceneNode]. +class SceneNode extends NativeFieldWrapperClass1 { + @pragma('vm:entry-point') + SceneNode._create() { + _constructor(); + } + + String? _debugName; + + void setTransform(Float64List matrix4) { + _setTransform(matrix4); + } + + void setAnimationState(String animationName, bool playing, double weight, double timeScale) { + _setAnimationState(animationName, playing, weight, timeScale); + } + + void seekAnimation(String animationName, double time) { + _seekAnimation(animationName, time); + } + + /// Creates a scene node from the asset with key [assetKey]. + /// + /// The asset must be a file produced as the output of the `scenec` importer. + /// The constructed object should then be reused via the [shader] + /// method to create [Shader] objects that can be used by [Shader.paint]. + static Future fromAsset(String assetKey) { + // The flutter tool converts all asset keys with spaces into URI + // encoded paths (replacing ' ' with '%20', for example). We perform + // the same encoding here so that users can load assets with the same + // key they have written in the pubspec. + final String encodedKey = Uri(path: Uri.encodeFull(assetKey)).path; + { + final SceneNode? scene_node = _ipsceneRegistry[encodedKey]?.target; + if (scene_node != null) { + return Future.value(scene_node); + } + } + + final SceneNode scene_node = SceneNode._create(); + return _futurize((_Callback callback) { + final String error = scene_node._initFromAsset(assetKey, callback); + if (error.isNotEmpty) { + return error; + } + assert(() { + scene_node._debugName = assetKey; + return true; + }()); + + _ipsceneRegistry[encodedKey] = WeakReference(scene_node); + }).then((_) => scene_node); + } + + // This is a cache of scene nodes that have been loaded by + // SceneNode.fromAsset. It holds weak references to the SceneNodes + // so that the case where an in-use program is requested again can be fast, + // but programs that are no longer referenced are not retained because of the + // cache. + static final Map> _ipsceneRegistry = + >{}; + + static void _reinitializeScene(String assetKey) { + // If a shader for the asset isn't already registered, then there's no + // need to reinitialize it. The new shader will be loaded and initialized + // the next time the program accesses it. + final WeakReference? nodeRef = _ipsceneRegistry == null + ? null + : _ipsceneRegistry[assetKey]; + if (nodeRef == null) { + return; + } + + final SceneNode? program = nodeRef.target; + if (program == null) { + return; + } + + final String result = program._initFromAsset(assetKey, (_) => {}); + if (result.isNotEmpty) { + throw result; // ignore: only_throw_errors + } + } + + @FfiNative('SceneNode::Create') + external void _constructor(); + + @FfiNative, Handle, Handle)>('SceneNode::initFromAsset') + external String _initFromAsset(String assetKey, _Callback completion_callback); + + @FfiNative, Handle)>('SceneNode::initFromTransform') + external void _initFromTransform(Float64List matrix4); + + @FfiNative, Handle)>('SceneNode::AddChild') + external void _addChild(SceneNode sceneNode); + + @FfiNative, Handle)>('SceneNode::SetTransform') + external void _setTransform(Float64List matrix4); + + @FfiNative, Handle, Handle, Handle, Handle)>('SceneScene::SetAnimationState') + external void _setAnimationState(String animationName, bool playing, double weight, double timeScale); + + @FfiNative, Handle, Handle)>('SceneNode::SeekAnimation') + external void _seekAnimation(String animationName, double time); + + /// Returns a fresh instance of [SceneShader]. + SceneShader sceneShader() => SceneShader._(this, debugName: _debugName); +} + +/// A [Shader] generated from a [SceneNode]. +/// +/// Instances of this class can be obtained from the +/// [SceneNode.sceneShader] method. +class SceneShader extends Shader { + SceneShader._(SceneNode node, { String? debugName }) : _debugName = debugName, super._() { + _constructor(node); + } + + final String? _debugName; + + /// Releases the native resources held by the [SceneShader]. + /// + /// After this method is called, calling methods on the shader, or attaching + /// it to a [Paint] object will fail with an exception. Calling [dispose] + /// twice will also result in an exception being thrown. + @override + void dispose() { + super.dispose(); + _dispose(); + } + + @FfiNative, Handle)>('SceneShader::Create') + external Float32List _constructor(SceneNode node); + + @FfiNative)>('SceneShader::Dispose') + external void _dispose(); +} diff --git a/lib/ui/experiments/ui.dart b/lib/ui/experiments/ui.dart index e6ee89e1097d2..e3846b1f2cb84 100644 --- a/lib/ui/experiments/ui.dart +++ b/lib/ui/experiments/ui.dart @@ -25,7 +25,6 @@ import 'dart:typed_data'; part '../annotations.dart'; part '../channel_buffers.dart'; part '../compositing.dart'; -part 'compositing_3d.dart'; part '../geometry.dart'; part '../hash_codes.dart'; part '../hooks.dart'; @@ -38,6 +37,7 @@ part '../painting.dart'; part '../platform_dispatcher.dart'; part '../plugins.dart'; part '../pointer.dart'; +part 'scene.dart'; part '../semantics.dart'; part '../text.dart'; part '../window.dart'; diff --git a/lib/ui/painting/fragment_program.h b/lib/ui/painting/fragment_program.h index 50da9cbf9dba0..484549104395e 100644 --- a/lib/ui/painting/fragment_program.h +++ b/lib/ui/painting/fragment_program.h @@ -7,7 +7,6 @@ #include "flutter/display_list/display_list_runtime_effect.h" #include "flutter/lib/ui/dart_wrapper.h" -#include "flutter/lib/ui/painting/fragment_shader.h" #include "flutter/lib/ui/painting/shader.h" #include "third_party/tonic/dart_library_natives.h" diff --git a/lib/ui/painting/scene/scene_node.cc b/lib/ui/painting/scene/scene_node.cc new file mode 100644 index 0000000000000..5967208c16cf0 --- /dev/null +++ b/lib/ui/painting/scene/scene_node.cc @@ -0,0 +1,109 @@ +// 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/lib/ui/painting/scene/scene_node.h" + +#include +#include + +#include "flutter/assets/asset_manager.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/fml/trace_event.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "flutter/lib/ui/painting/scene/scene_shader.h" +#include "flutter/lib/ui/ui_dart_state.h" +#include "flutter/lib/ui/window/platform_configuration.h" +#include "impeller/geometry/matrix.h" +#include "impeller/scene/animation/property_resolver.h" + +#include "third_party/tonic/converter/dart_converter.h" +#include "third_party/tonic/dart_args.h" +#include "third_party/tonic/dart_binding_macros.h" +#include "third_party/tonic/dart_library_natives.h" + +namespace flutter { + +IMPLEMENT_WRAPPERTYPEINFO(ui, SceneNode); + +void SceneNode::Create(Dart_Handle wrapper) { + auto res = fml::MakeRefCounted(); + res->AssociateWithDartWrapper(wrapper); +} + +std::string SceneNode::initFromAsset(const std::string& asset_name, + Dart_Handle completion_callback_handle) { + FML_TRACE_EVENT("flutter", "SceneNode::initFromAsset", "asset", asset_name); + + if (!Dart_IsClosure(completion_callback_handle)) { + return "Completion callback must be a function."; + } + + if (!UIDartState::Current()->IsImpellerEnabled()) { + return "3D scenes require the Impeller rendering backend to be enabled."; + } + + std::shared_ptr asset_manager = UIDartState::Current() + ->platform_configuration() + ->client() + ->GetAssetManager(); + std::unique_ptr data = asset_manager->GetAsMapping(asset_name); + if (data == nullptr) { + return std::string("Asset '") + asset_name + std::string("' not found."); + } + + UIDartState::Current()->GetTaskRunners().GetRasterTaskRunner()->PostTask( + fml::MakeCopyable( + [this, completion_callback_handle, data = std::move(data)]() { + auto& context = + *UIDartState::Current()->GetIOManager()->GetImpellerContext(); + node_ = impeller::scene::Node::MakeFromFlatbuffer( + *data, *context.GetResourceAllocator()); + tonic::DartInvoke(completion_callback_handle, {Dart_TypeVoid()}); + })); + + return ""; +} + +void SceneNode::initFromTransform(const tonic::Float64List& matrix4) { + node_ = std::make_shared(); + node_->SetLocalTransform( + impeller::Matrix(matrix4[0], matrix4[4], matrix4[8], matrix4[12], // + matrix4[1], matrix4[5], matrix4[9], matrix4[13], // + matrix4[2], matrix4[6], matrix4[10], matrix4[14], // + matrix4[3], matrix4[7], matrix4[11], matrix4[15])); +} + +void SceneNode::AddChild(Dart_Handle scene_node_handle) { + if (!node_) { + return; + } + auto* scene_node = + tonic::DartConverter::FromDart(scene_node_handle); + if (!scene_node) { + return; + } + node_->AddChild(scene_node->node_); + children_.push_back(fml::Ref(scene_node)); +} + +void SceneNode::SetTransform(const tonic::Float64List& matrix4) { + // TODO(bdero): Implement mutation log. +} + +void SceneNode::SetAnimationState(const std::string& animation_name, + bool playing, + double weight, + double time_scale) { + // TODO(bdero): Implement mutation log. +} + +void SceneNode::SeekAnimation(const std::string& animation_name, double time) { + // TODO(bdero): Implement mutation log. +} + +SceneNode::SceneNode() = default; + +SceneNode::~SceneNode() = default; + +} // namespace flutter diff --git a/lib/ui/painting/scene/scene_node.h b/lib/ui/painting/scene/scene_node.h new file mode 100644 index 0000000000000..563b0f9232c55 --- /dev/null +++ b/lib/ui/painting/scene/scene_node.h @@ -0,0 +1,67 @@ +// 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_LIB_UI_PAINTING_SCENE_NODE_H_ +#define FLUTTER_LIB_UI_PAINTING_SCENE_NODE_H_ + +#include +#include +#include + +#include "flutter/fml/memory/ref_ptr.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "flutter/lib/ui/painting/shader.h" + +#include "third_party/tonic/dart_library_natives.h" + +namespace flutter { + +class SceneShader; + +/// @brief A scene node, which may be a deserialized ipscene asset. This node +/// can be safely added as a child to multiple scene nodes, whether +/// they're in the same scene or a different scene. The deserialized +/// node itself is treated as immutable on the IO thread. +/// +/// Internally, nodes may have an animation player, which is controlled +/// via the mutation log in the `DlSceneColorSource`, which is built by +/// `SceneShader`. +class SceneNode : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(SceneShader); + + public: + SceneNode(); + ~SceneNode() override; + + static void Create(Dart_Handle wrapper); + + std::string initFromAsset(const std::string& asset_name, + Dart_Handle completion_callback_handle); + + void initFromTransform(const tonic::Float64List& matrix4); + + void AddChild(Dart_Handle scene_node_handle); + + void SetTransform(const tonic::Float64List& matrix4); + + void SetAnimationState(const std::string& animation_name, + bool playing, + double weight, + double time_scale); + + void SeekAnimation(const std::string& animation_name, double time); + + fml::RefPtr node(Dart_Handle shader); + + private: + std::shared_ptr node_; + std::vector> children_; + + friend SceneShader; +}; + +} // namespace flutter + +#endif // FLUTTER_LIB_UI_PAINTING_SCENE_NODE_H_ diff --git a/lib/ui/painting/scene/scene_shader.cc b/lib/ui/painting/scene/scene_shader.cc new file mode 100644 index 0000000000000..1dabe51861122 --- /dev/null +++ b/lib/ui/painting/scene/scene_shader.cc @@ -0,0 +1,82 @@ +// 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/lib/ui/painting/scene/scene_shader.h" + +#include +#include + +#include "flutter/display_list/display_list_color_source.h" +#include "flutter/display_list/display_list_tile_mode.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "flutter/lib/ui/painting/scene/scene_node.h" +#include "flutter/lib/ui/ui_dart_state.h" +#include "impeller/geometry/scalar.h" +#include "impeller/geometry/size.h" + +#include "third_party/tonic/converter/dart_converter.h" +#include "third_party/tonic/dart_args.h" +#include "third_party/tonic/dart_binding_macros.h" +#include "third_party/tonic/dart_library_natives.h" +#include "third_party/tonic/typed_data/typed_list.h" + +namespace flutter { + +IMPLEMENT_WRAPPERTYPEINFO(ui, SceneShader); + +SceneShader::SceneShader(fml::RefPtr scene_node) + : scene_node_(std::move(scene_node)) {} + +void SceneShader::Create(Dart_Handle wrapper, Dart_Handle scene_node_handle) { + auto* scene_node = + tonic::DartConverter::FromDart(scene_node_handle); + if (!scene_node) { + return; + } + + auto res = fml::MakeRefCounted(fml::Ref(scene_node)); + res->AssociateWithDartWrapper(wrapper); +} + +void SceneShader::SetCameraTransform(const tonic::Float64List& matrix4) { + camera_transform_ = + impeller::Matrix(matrix4[0], matrix4[4], matrix4[8], matrix4[12], // + matrix4[1], matrix4[5], matrix4[9], matrix4[13], // + matrix4[2], matrix4[6], matrix4[10], matrix4[14], // + matrix4[3], matrix4[7], matrix4[11], matrix4[15]); +} + +static impeller::Matrix DefaultCameraTransform() { + // TODO(bdero): There's not way to know what the draw area will be yet, so + // make the DlSceneColorSource camera transform optional and + // defer this default (or parameterize the camera instead). + return impeller::Matrix::MakePerspective( + impeller::Degrees(45), impeller::ISize{800, 600}, 0.1, 1000) * + impeller::Matrix::MakeLookAt({0, 0, -5}, {0, 0, 0}, {0, 1, 0}); +} + +std::shared_ptr SceneShader::shader(DlImageSampling sampling) { + FML_CHECK(scene_node_); + + if (!scene_node_->node_) { + return nullptr; + } + + // TODO(bdero): Gather the mutation log and include it in the scene color + // source. + + return std::make_shared(scene_node_->node_, + camera_transform_.IsIdentity() + ? DefaultCameraTransform() + : camera_transform_); +} + +void SceneShader::Dispose() { + scene_node_ = nullptr; + ClearDartWrapper(); +} + +SceneShader::~SceneShader() = default; + +} // namespace flutter diff --git a/lib/ui/painting/scene/scene_shader.h b/lib/ui/painting/scene/scene_shader.h new file mode 100644 index 0000000000000..c3d4be37447d1 --- /dev/null +++ b/lib/ui/painting/scene/scene_shader.h @@ -0,0 +1,45 @@ +// 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_LIB_UI_PAINTING_SCENE_SHADER_H_ +#define FLUTTER_LIB_UI_PAINTING_SCENE_SHADER_H_ + +#include +#include + +#include "flutter/lib/ui/dart_wrapper.h" +#include "flutter/lib/ui/painting/scene/scene_node.h" +#include "flutter/lib/ui/painting/shader.h" +#include "impeller/geometry/matrix.h" + +#include "third_party/tonic/dart_library_natives.h" + +namespace flutter { + +class SceneShader : public Shader { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(SceneShader); + + public: + ~SceneShader() override; + + static void Create(Dart_Handle wrapper, Dart_Handle scene_node_handle); + + void SetCameraTransform(const tonic::Float64List& matrix4); + + void Dispose(); + + // |Shader| + std::shared_ptr shader(DlImageSampling) override; + + private: + explicit SceneShader(fml::RefPtr scene_node); + + impeller::Matrix camera_transform_; + fml::RefPtr scene_node_; +}; + +} // namespace flutter + +#endif // FLUTTER_LIB_UI_PAINTING_SCENE_SHADER_H_ From ba2d970b6204c18bc8f9eee810622b889b235ecc Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 14:42:11 -0800 Subject: [PATCH 03/24] Address build failures --- display_list/BUILD.gn | 9 ++- display_list/display_list_builder.cc | 2 + display_list/display_list_color_source.h | 13 +++- display_list/display_list_ops.h | 2 + impeller/display_list/BUILD.gn | 7 ++ .../display_list/display_list_dispatcher.cc | 7 +- lib/ui/BUILD.gn | 13 ++-- lib/ui/experiments/scene.dart | 77 ++++++++----------- 8 files changed, 78 insertions(+), 52 deletions(-) diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 0cf553b355ad2..32756ec2597df 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -69,9 +69,16 @@ source_set("display_list") { public_deps = [ "//flutter/fml", "//flutter/impeller/runtime_stage", - "//flutter/impeller/scene", "//third_party/skia", ] + + if (!defined(defines)) { + defines = [] + } + if (impeller_enable_3d) { + defines += [ "IMPELLER_ENABLE_3D" ] + public_deps += [ "//flutter/impeller/scene" ] + } } if (enable_unittests) { diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index 0d7669954abcd..b63d2e355bbec 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -203,12 +203,14 @@ void DisplayListBuilder::onSetColorSource(const DlColorSource* source) { Push(0, 0, effect); break; } +#ifdef IMPELLER_ENABLE_3D case DlColorSourceType::kScene: { const DlSceneColorSource* scene = source->asScene(); FML_DCHECK(scene); Push(0, 0, scene); break; } +#endif // IMPELLER_ENABLE_3D case DlColorSourceType::kUnknown: Push(0, 0, source->skia_object()); break; diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index 4ac78a3b2b632..87c3d8acf5ee8 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -19,11 +19,17 @@ #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" #include "impeller/geometry/matrix.h" -#include "impeller/scene/node.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkRuntimeEffect.h" +#ifdef IMPELLER_ENABLE_3D +#include "impeller/scene/node.h" +namespace flutter { +class DlSceneColorSource; +} +#endif // IMPELLER_ENABLE_3D + namespace flutter { class DlColorColorSource; @@ -33,7 +39,6 @@ class DlRadialGradientColorSource; class DlConicalGradientColorSource; class DlSweepGradientColorSource; class DlRuntimeEffectColorSource; -class DlSceneColorSource; class DlUnknownColorSource; // The DisplayList ColorSource class. This class implements all of the @@ -164,7 +169,9 @@ class DlColorSource return nullptr; } +#ifdef IMPELLER_ENABLE_3D virtual const DlSceneColorSource* asScene() const { return nullptr; } +#endif // IMPELLER_ENABLE_3D // If this filter contains images, specifies the owning context for those // images. @@ -760,6 +767,7 @@ class DlRuntimeEffectColorSource final : public DlColorSource { FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlRuntimeEffectColorSource); }; +#ifdef IMPELLER_ENABLE_3D class DlSceneColorSource final : public DlColorSource { public: DlSceneColorSource(std::shared_ptr node, @@ -799,6 +807,7 @@ class DlSceneColorSource final : public DlColorSource { FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlSceneColorSource); }; +#endif // IMPELLER_ENABLE_3D class DlUnknownColorSource final : public DlColorSource { public: diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h index d147caafc2659..d4f42f4906b5d 100644 --- a/display_list/display_list_ops.h +++ b/display_list/display_list_ops.h @@ -312,6 +312,7 @@ struct SetRuntimeEffectColorSourceOp : DLOp { } }; +#ifdef IMPELLER_ENABLE_3D struct SetSceneColorSourceOp : DLOp { static const auto kType = DisplayListOpType::kSetSceneColorSource; @@ -329,6 +330,7 @@ struct SetSceneColorSourceOp : DLOp { : DisplayListCompare::kNotEqual; } }; +#endif // IMPELLER_ENABLE_3D // 4 byte header + 16 byte payload uses 24 total bytes (4 bytes unused) struct SetSharedImageFilterOp : DLOp { diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn index 48cf0f1619f38..0d58c3c4d5245 100644 --- a/impeller/display_list/BUILD.gn +++ b/impeller/display_list/BUILD.gn @@ -22,6 +22,13 @@ impeller_component("display_list") { "//flutter/fml", "//third_party/skia", ] + + if (!defined(defines)) { + defines = [] + } + if (impeller_enable_3d) { + defines += [ "IMPELLER_ENABLE_3D" ] + } } impeller_component("display_list_unittests") { diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 891f37768cb47..ea1194bda54c3 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -504,6 +504,7 @@ void DisplayListDispatcher::setColorSource( return; } case Paint::ColorSourceType::kScene: { +#ifdef IMPELLER_ENABLE_3D const flutter::DlSceneColorSource* scene_color_source = source->asScene(); std::shared_ptr scene_node = scene_color_source->scene_node(); @@ -515,8 +516,12 @@ void DisplayListDispatcher::setColorSource( contents->SetCameraTransform(camera_transform); return contents; }; - } +#else // IMPELLER_ENABLE_3D + FML_LOG(ERROR) << "ColorSourceType::kScene can only be used if Impeller " + "Scene is enabled."; +#endif // IMPELLER_ENABLE_3D return; + } case Paint::ColorSourceType::kConicalGradient: UNIMPLEMENTED; break; diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index c84e8dbd62ae8..adaec644f017b 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -81,10 +81,6 @@ source_set("ui") { "painting/picture_recorder.h", "painting/rrect.cc", "painting/rrect.h", - "painting/scene/scene_node.cc", - "painting/scene/scene_node.h", - "painting/scene/scene_shader.cc", - "painting/scene/scene_shader.h", "painting/shader.cc", "painting/shader.h", "painting/single_frame_codec.cc", @@ -159,7 +155,6 @@ source_set("ui") { "//flutter/display_list", "//flutter/fml", "//flutter/impeller/runtime_stage", - "//flutter/impeller/scene", "//flutter/runtime:dart_plugin_registrant", "//flutter/runtime:test_font", "//flutter/third_party/tonic", @@ -196,6 +191,14 @@ source_set("ui") { } if (impeller_enable_3d) { defines += [ "IMPELLER_ENABLE_3D" ] + sources += [ + "painting/scene/scene_node.cc", + "painting/scene/scene_node.h", + "painting/scene/scene_shader.cc", + "painting/scene/scene_shader.h", + ] + + deps += [ "//flutter/impeller/scene" ] } } diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart index 7a38d37d8168d..65657245e1b3f 100644 --- a/lib/ui/experiments/scene.dart +++ b/lib/ui/experiments/scene.dart @@ -12,18 +12,6 @@ class SceneNode extends NativeFieldWrapperClass1 { String? _debugName; - void setTransform(Float64List matrix4) { - _setTransform(matrix4); - } - - void setAnimationState(String animationName, bool playing, double weight, double timeScale) { - _setAnimationState(animationName, playing, weight, timeScale); - } - - void seekAnimation(String animationName, double time) { - _seekAnimation(animationName, time); - } - /// Creates a scene node from the asset with key [assetKey]. /// /// The asset must be a file produced as the output of the `scenec` importer. @@ -36,25 +24,49 @@ class SceneNode extends NativeFieldWrapperClass1 { // key they have written in the pubspec. final String encodedKey = Uri(path: Uri.encodeFull(assetKey)).path; { - final SceneNode? scene_node = _ipsceneRegistry[encodedKey]?.target; - if (scene_node != null) { - return Future.value(scene_node); + final SceneNode? sceneNode = _ipsceneRegistry[encodedKey]?.target; + if (sceneNode != null) { + return Future.value(sceneNode); } } - final SceneNode scene_node = SceneNode._create(); + final SceneNode sceneNode = SceneNode._create(); return _futurize((_Callback callback) { - final String error = scene_node._initFromAsset(assetKey, callback); + final String error = sceneNode._initFromAsset(assetKey, callback); if (error.isNotEmpty) { return error; } assert(() { - scene_node._debugName = assetKey; + sceneNode._debugName = assetKey; return true; }()); - _ipsceneRegistry[encodedKey] = WeakReference(scene_node); - }).then((_) => scene_node); + _ipsceneRegistry[encodedKey] = WeakReference(sceneNode); + + return null; + }).then((_) => sceneNode); + } + + static SceneNode fromTransform(Float64List matrix4) { + final SceneNode sceneNode = SceneNode._create(); + sceneNode._initFromTransform(matrix4); + return sceneNode; + } + + void addChild(SceneNode sceneNode) { + _addChild(sceneNode); + } + + void setTransform(Float64List matrix4) { + _setTransform(matrix4); + } + + void setAnimationState(String animationName, bool playing, double weight, double timeScale) { + _setAnimationState(animationName, playing, weight, timeScale); + } + + void seekAnimation(String animationName, double time) { + _seekAnimation(animationName, time); } // This is a cache of scene nodes that have been loaded by @@ -65,33 +77,11 @@ class SceneNode extends NativeFieldWrapperClass1 { static final Map> _ipsceneRegistry = >{}; - static void _reinitializeScene(String assetKey) { - // If a shader for the asset isn't already registered, then there's no - // need to reinitialize it. The new shader will be loaded and initialized - // the next time the program accesses it. - final WeakReference? nodeRef = _ipsceneRegistry == null - ? null - : _ipsceneRegistry[assetKey]; - if (nodeRef == null) { - return; - } - - final SceneNode? program = nodeRef.target; - if (program == null) { - return; - } - - final String result = program._initFromAsset(assetKey, (_) => {}); - if (result.isNotEmpty) { - throw result; // ignore: only_throw_errors - } - } - @FfiNative('SceneNode::Create') external void _constructor(); @FfiNative, Handle, Handle)>('SceneNode::initFromAsset') - external String _initFromAsset(String assetKey, _Callback completion_callback); + external String _initFromAsset(String assetKey, _Callback completionCallback); @FfiNative, Handle)>('SceneNode::initFromTransform') external void _initFromTransform(Float64List matrix4); @@ -121,6 +111,7 @@ class SceneShader extends Shader { _constructor(node); } + // ignore: unused_field final String? _debugName; /// Releases the native resources held by the [SceneShader]. From ba045de545b30568675aa80892f22404dada5bbd Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 15:06:23 -0800 Subject: [PATCH 04/24] Address failures 2 --- display_list/display_list_color_source.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index 87c3d8acf5ee8..37056864c1826 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -18,12 +18,12 @@ #include "flutter/display_list/display_list_tile_mode.h" #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" -#include "impeller/geometry/matrix.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkRuntimeEffect.h" #ifdef IMPELLER_ENABLE_3D +#include "impeller/geometry/matrix.h" #include "impeller/scene/node.h" namespace flutter { class DlSceneColorSource; From 9073c44115d1e2c0cb839120dbb36ed58c978432 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 15:21:35 -0800 Subject: [PATCH 05/24] Add nogncheck to conditional includes --- display_list/BUILD.gn | 2 +- display_list/display_list_color_source.h | 4 ++-- impeller/tools/impeller.gni | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 32756ec2597df..db06b675de556 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -76,7 +76,7 @@ source_set("display_list") { defines = [] } if (impeller_enable_3d) { - defines += [ "IMPELLER_ENABLE_3D" ] + #defines += [ "IMPELLER_ENABLE_3D" ] public_deps += [ "//flutter/impeller/scene" ] } } diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index 37056864c1826..a415581b97054 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -23,8 +23,8 @@ #include "third_party/skia/include/effects/SkRuntimeEffect.h" #ifdef IMPELLER_ENABLE_3D -#include "impeller/geometry/matrix.h" -#include "impeller/scene/node.h" +#include "impeller/geometry/matrix.h" // nogncheck +#include "impeller/scene/node.h" // nogncheck namespace flutter { class DlSceneColorSource; } diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni index d1fb6eb3ee7b9..e2c35817d64df 100644 --- a/impeller/tools/impeller.gni +++ b/impeller/tools/impeller.gni @@ -36,7 +36,7 @@ declare_args() { # Call glGetError after each OpenGL call and log failures. impeller_error_check_all_gl_calls = is_debug - # Eperimentally enable 3d code paths. + # Enable experimental 3D scene rendering. impeller_enable_3d = false } From 65488a11d04fc09e8ddb69d1db67981069a62d66 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 15:23:02 -0800 Subject: [PATCH 06/24] Whoops --- display_list/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index db06b675de556..32756ec2597df 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -76,7 +76,7 @@ source_set("display_list") { defines = [] } if (impeller_enable_3d) { - #defines += [ "IMPELLER_ENABLE_3D" ] + defines += [ "IMPELLER_ENABLE_3D" ] public_deps += [ "//flutter/impeller/scene" ] } } From ad50a683c28545cf7773f823e650fc3708ee4459 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 15:27:34 -0800 Subject: [PATCH 07/24] Conditionally include in op enum --- display_list/display_list_color_source.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index a415581b97054..361e7b2817b01 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -59,7 +59,9 @@ enum class DlColorSourceType { kConicalGradient, kSweepGradient, kRuntimeEffect, +#ifdef IMPELLER_ENABLE_3D kScene, +#endif // IMPELLER_ENABLE_3D kUnknown }; From f9aa1cfac705ad239a0476b38c9d5ba1cb0e96c3 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 15:38:02 -0800 Subject: [PATCH 08/24] More build fixes --- display_list/display_list.h | 8 ++++++-- impeller/display_list/display_list_dispatcher.cc | 2 ++ lib/ui/dart_ui.cc | 7 +++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/display_list/display_list.h b/display_list/display_list.h index 8d26950826322..1ee8645960737 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -91,7 +91,6 @@ namespace flutter { V(SetSkColorSource) \ V(SetImageColorSource) \ V(SetRuntimeEffectColorSource) \ - V(SetSceneColorSource) \ \ V(ClearImageFilter) \ V(SetPodImageFilter) \ @@ -160,7 +159,12 @@ namespace flutter { V(DrawShadowTransparentOccluder) #define DL_OP_TO_ENUM_VALUE(name) k##name, -enum class DisplayListOpType { FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) }; +enum class DisplayListOpType { + FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) +#ifdef IMPELLER_ENABLE_3D + DL_OP_TO_ENUM_VALUE(SetSceneColorSource) +#endif // IMPELLER_ENABLE_3D +}; #undef DL_OP_TO_ENUM_VALUE class Dispatcher; diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index ea1194bda54c3..0f9b0de500f37 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -337,8 +337,10 @@ static std::optional ToColorSourceType( return Paint::ColorSourceType::kSweepGradient; case flutter::DlColorSourceType::kRuntimeEffect: return Paint::ColorSourceType::kRuntimeEffect; +#ifdef IMPELLER_ENABLE_3D case flutter::DlColorSourceType::kScene: return Paint::ColorSourceType::kScene; +#endif // IMPELLER_ENABLE_3D case flutter::DlColorSourceType::kUnknown: return std::nullopt; } diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index aa7ecb832df12..86099f8124135 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -29,8 +29,6 @@ #include "flutter/lib/ui/painting/path_measure.h" #include "flutter/lib/ui/painting/picture.h" #include "flutter/lib/ui/painting/picture_recorder.h" -#include "flutter/lib/ui/painting/scene/scene_node.h" -#include "flutter/lib/ui/painting/scene/scene_shader.h" #include "flutter/lib/ui/painting/vertices.h" #include "flutter/lib/ui/semantics/semantics_update.h" #include "flutter/lib/ui/semantics/semantics_update_builder.h" @@ -43,6 +41,11 @@ #include "third_party/tonic/dart_args.h" #include "third_party/tonic/logging/dart_error.h" +#ifdef IMPELLER_ENABLE_3D +#include "flutter/lib/ui/painting/scene/scene_node.h" +#include "flutter/lib/ui/painting/scene/scene_shader.h" +#endif // IMPELLER_ENABLE_3D + using tonic::ToDart; namespace flutter { From 6c070e8924f23f0dd02e099e5e81f8aefe221ba6 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 19:13:46 -0800 Subject: [PATCH 09/24] Add hotreload hook --- ci/licenses_golden/licenses_flutter | 4 +++ lib/ui/experiments/scene.dart | 38 ++++++++++++++++++--- lib/ui/experiments/setup_hooks.dart | 28 ++++++++++++++++ lib/ui/experiments/ui.dart | 1 + lib/ui/natives.dart | 23 ------------- lib/ui/setup_hooks.dart | 51 +++++++++++++++++++++++++++++ lib/ui/ui.dart | 1 + 7 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 lib/ui/experiments/setup_hooks.dart create mode 100644 lib/ui/setup_hooks.dart diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 93d013ea75816..d705ac98a1d99 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1704,6 +1704,7 @@ ORIGIN: ../../../flutter/lib/ui/dart_ui.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/dart_ui.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/dart_wrapper.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/experiments/scene.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/experiments/setup_hooks.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/experiments/ui.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/geometry.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/hash_codes.dart + ../../../flutter/LICENSE @@ -1809,6 +1810,7 @@ ORIGIN: ../../../flutter/lib/ui/semantics/semantics_update_builder.cc + ../../.. ORIGIN: ../../../flutter/lib/ui/semantics/semantics_update_builder.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/semantics/string_attribute.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/semantics/string_attribute.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/setup_hooks.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/snapshot_delegate.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/text.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/text/asset_manager_font_provider.cc + ../../../flutter/LICENSE @@ -4180,6 +4182,7 @@ FILE: ../../../flutter/lib/ui/dart_ui.cc FILE: ../../../flutter/lib/ui/dart_ui.h FILE: ../../../flutter/lib/ui/dart_wrapper.h FILE: ../../../flutter/lib/ui/experiments/scene.dart +FILE: ../../../flutter/lib/ui/experiments/setup_hooks.dart FILE: ../../../flutter/lib/ui/experiments/ui.dart FILE: ../../../flutter/lib/ui/geometry.dart FILE: ../../../flutter/lib/ui/hash_codes.dart @@ -4285,6 +4288,7 @@ FILE: ../../../flutter/lib/ui/semantics/semantics_update_builder.cc FILE: ../../../flutter/lib/ui/semantics/semantics_update_builder.h FILE: ../../../flutter/lib/ui/semantics/string_attribute.cc FILE: ../../../flutter/lib/ui/semantics/string_attribute.h +FILE: ../../../flutter/lib/ui/setup_hooks.dart FILE: ../../../flutter/lib/ui/snapshot_delegate.h FILE: ../../../flutter/lib/ui/text.dart FILE: ../../../flutter/lib/ui/text/asset_manager_font_provider.cc diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart index 65657245e1b3f..e93643229aa0c 100644 --- a/lib/ui/experiments/scene.dart +++ b/lib/ui/experiments/scene.dart @@ -69,14 +69,42 @@ class SceneNode extends NativeFieldWrapperClass1 { _seekAnimation(animationName, time); } - // This is a cache of scene nodes that have been loaded by - // SceneNode.fromAsset. It holds weak references to the SceneNodes - // so that the case where an in-use program is requested again can be fast, - // but programs that are no longer referenced are not retained because of the - // cache. + // This is a cache of ipscene-backed scene nodes that have been loaded via + // SceneNode.fromAsset. It holds weak references to the SceneNodes so that the + // case where an in-use ipscene is requested again can be fast, but scenes + // that are no longer referenced are not retained because of the cache. static final Map> _ipsceneRegistry = >{}; + static void _reinitializeScene(String assetKey) async { + // If a scene for the asset isn't already registered, then there's no + // need to reinitialize it. + final WeakReference? sceneRef = _ipsceneRegistry == null + ? null + : _ipsceneRegistry[assetKey]; + if (sceneRef == null) { + return; + } + + final SceneNode? scene = sceneRef.target; + if (scene == null) { + return; + } + + final String result = scene._initFromAsset(assetKey); + if (result.isNotEmpty) { + throw result; // ignore: only_throw_errors + } + + await _futurize((_Callback callback) { + final String error = sceneNode._initFromAsset(assetKey, callback); + if (error.isNotEmpty) { + return error; + } + return null; + }); + } + @FfiNative('SceneNode::Create') external void _constructor(); diff --git a/lib/ui/experiments/setup_hooks.dart b/lib/ui/experiments/setup_hooks.dart new file mode 100644 index 0000000000000..ff33e8c9c8623 --- /dev/null +++ b/lib/ui/experiments/setup_hooks.dart @@ -0,0 +1,28 @@ +// 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. + +part of dart.ui; + +@pragma('vm:entry-point') +void _setupHooks() { + assert(() { + // In debug mode, register the schedule frame extension. + developer.registerExtension('ext.ui.window.scheduleFrame', _scheduleFrame); + + // In debug mode, allow shaders to be reinitialized. + developer.registerExtension( + 'ext.ui.window.reinitializeShader', + _reinitializeShader, + ); + return true; + }()); + + // In debug and profile mode, allow tools to display the current rendering backend. + if (!_kReleaseMode) { + developer.registerExtension( + 'ext.ui.window.impellerEnabled', + _getImpellerEnabled, + ); + } +} diff --git a/lib/ui/experiments/ui.dart b/lib/ui/experiments/ui.dart index e3846b1f2cb84..41d3fcfece6c4 100644 --- a/lib/ui/experiments/ui.dart +++ b/lib/ui/experiments/ui.dart @@ -39,5 +39,6 @@ part '../plugins.dart'; part '../pointer.dart'; part 'scene.dart'; part '../semantics.dart'; +part 'setup_hooks.dart'; part '../text.dart'; part '../window.dart'; diff --git a/lib/ui/natives.dart b/lib/ui/natives.dart index 49a567e5b5db6..4fb41bfb41137 100644 --- a/lib/ui/natives.dart +++ b/lib/ui/natives.dart @@ -83,29 +83,6 @@ Future _getImpellerEnabled( })); } -@pragma('vm:entry-point') -void _setupHooks() { - assert(() { - // In debug mode, register the schedule frame extension. - developer.registerExtension('ext.ui.window.scheduleFrame', _scheduleFrame); - - // In debug mode, allow shaders to be reinitialized. - developer.registerExtension( - 'ext.ui.window.reinitializeShader', - _reinitializeShader, - ); - return true; - }()); - - // In debug and profile mode, allow tools to display the current rendering backend. - if (!_kReleaseMode) { - developer.registerExtension( - 'ext.ui.window.impellerEnabled', - _getImpellerEnabled, - ); - } -} - const bool _kReleaseMode = bool.fromEnvironment('dart.vm.product'); /// Returns runtime Dart compilation trace as a UTF-8 encoded memory buffer. diff --git a/lib/ui/setup_hooks.dart b/lib/ui/setup_hooks.dart new file mode 100644 index 0000000000000..8d5dfdd966da8 --- /dev/null +++ b/lib/ui/setup_hooks.dart @@ -0,0 +1,51 @@ +// 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. + +part of dart.ui; + +Future _reinitializeScene( + String method, + Map parameters, +) async { + final String? assetKey = parameters['assetKey']; + if (assetKey != null) { + await SceneNode._reinitializeScene(assetKey); + } + + // Always succeed. + return developer.ServiceExtensionResponse.result(json.encode({ + 'type': 'Success', + })); +} + +// This is a copy of ui/setup_hooks.dart, but with reinitializeScene added for hot reloading 3D scenes. + +@pragma('vm:entry-point') +void _setupHooks() { + assert(() { + // In debug mode, register the schedule frame extension. + developer.registerExtension('ext.ui.window.scheduleFrame', _scheduleFrame); + + // In debug mode, allow shaders to be reinitialized. + developer.registerExtension( + 'ext.ui.window.reinitializeShader', + _reinitializeShader, + ); + + // In debug mode, allow 3D scenes to be reinitialized. + developer.registerExtension( + 'ext.ui.window.reinitializeScene', + _reinitializeScene, + ); + return true; + }()); + + // In debug and profile mode, allow tools to display the current rendering backend. + if (!_kReleaseMode) { + developer.registerExtension( + 'ext.ui.window.impellerEnabled', + _getImpellerEnabled, + ); + } +} diff --git a/lib/ui/ui.dart b/lib/ui/ui.dart index 36818d3c74480..e7f9558a359aa 100644 --- a/lib/ui/ui.dart +++ b/lib/ui/ui.dart @@ -38,5 +38,6 @@ part 'platform_dispatcher.dart'; part 'plugins.dart'; part 'pointer.dart'; part 'semantics.dart'; +part 'setup_hooks.dart'; part 'text.dart'; part 'window.dart'; From 18407cc3bdea0449d2f902ec608d144fb39ea27e Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 19:21:03 -0800 Subject: [PATCH 10/24] Fix build --- lib/ui/experiments/scene.dart | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart index e93643229aa0c..cd6c69b6321a4 100644 --- a/lib/ui/experiments/scene.dart +++ b/lib/ui/experiments/scene.dart @@ -77,25 +77,21 @@ class SceneNode extends NativeFieldWrapperClass1 { >{}; static void _reinitializeScene(String assetKey) async { - // If a scene for the asset isn't already registered, then there's no - // need to reinitialize it. final WeakReference? sceneRef = _ipsceneRegistry == null ? null : _ipsceneRegistry[assetKey]; + + // If a scene for the asset isn't already registered, then there's no + // need to reinitialize it. if (sceneRef == null) { return; } - final SceneNode? scene = sceneRef.target; - if (scene == null) { + final SceneNode? sceneNode = sceneRef.target; + if (sceneNode == null) { return; } - final String result = scene._initFromAsset(assetKey); - if (result.isNotEmpty) { - throw result; // ignore: only_throw_errors - } - await _futurize((_Callback callback) { final String error = sceneNode._initFromAsset(assetKey, callback); if (error.isNotEmpty) { From 42f31aaa12c96dd2add0a8a0773d071cfc74658f Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 20:00:48 -0800 Subject: [PATCH 11/24] Flip setup_hooks around --- lib/ui/experiments/setup_hooks.dart | 23 +++++++++++++++++++++++ lib/ui/setup_hooks.dart | 22 ---------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/ui/experiments/setup_hooks.dart b/lib/ui/experiments/setup_hooks.dart index ff33e8c9c8623..8d5dfdd966da8 100644 --- a/lib/ui/experiments/setup_hooks.dart +++ b/lib/ui/experiments/setup_hooks.dart @@ -4,6 +4,23 @@ part of dart.ui; +Future _reinitializeScene( + String method, + Map parameters, +) async { + final String? assetKey = parameters['assetKey']; + if (assetKey != null) { + await SceneNode._reinitializeScene(assetKey); + } + + // Always succeed. + return developer.ServiceExtensionResponse.result(json.encode({ + 'type': 'Success', + })); +} + +// This is a copy of ui/setup_hooks.dart, but with reinitializeScene added for hot reloading 3D scenes. + @pragma('vm:entry-point') void _setupHooks() { assert(() { @@ -15,6 +32,12 @@ void _setupHooks() { 'ext.ui.window.reinitializeShader', _reinitializeShader, ); + + // In debug mode, allow 3D scenes to be reinitialized. + developer.registerExtension( + 'ext.ui.window.reinitializeScene', + _reinitializeScene, + ); return true; }()); diff --git a/lib/ui/setup_hooks.dart b/lib/ui/setup_hooks.dart index 8d5dfdd966da8..cb79a052c25bf 100644 --- a/lib/ui/setup_hooks.dart +++ b/lib/ui/setup_hooks.dart @@ -4,23 +4,6 @@ part of dart.ui; -Future _reinitializeScene( - String method, - Map parameters, -) async { - final String? assetKey = parameters['assetKey']; - if (assetKey != null) { - await SceneNode._reinitializeScene(assetKey); - } - - // Always succeed. - return developer.ServiceExtensionResponse.result(json.encode({ - 'type': 'Success', - })); -} - -// This is a copy of ui/setup_hooks.dart, but with reinitializeScene added for hot reloading 3D scenes. - @pragma('vm:entry-point') void _setupHooks() { assert(() { @@ -33,11 +16,6 @@ void _setupHooks() { _reinitializeShader, ); - // In debug mode, allow 3D scenes to be reinitialized. - developer.registerExtension( - 'ext.ui.window.reinitializeScene', - _reinitializeScene, - ); return true; }()); From 50967f03fa114c33443f964028d88ecb45e67873 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 20:02:39 -0800 Subject: [PATCH 12/24] Add scene reload test --- lib/ui/BUILD.gn | 4 ++ testing/dart/observatory/BUILD.gn | 5 ++ testing/dart/observatory/README.md | 2 +- .../dart/observatory/scene_reload_test.dart | 63 +++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 testing/dart/observatory/scene_reload_test.dart diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index adaec644f017b..549713470df27 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -216,6 +216,10 @@ if (enable_unittests) { "fixtures/FontManifest.json", "//flutter/third_party/txt/third_party/fonts/Roboto-Medium.ttf", ] + + if (impeller_enable_3d) { + deps += [ "//flutter/impeller/fixtures:scene_fixtures" ] + } } executable("ui_benchmarks") { diff --git a/testing/dart/observatory/BUILD.gn b/testing/dart/observatory/BUILD.gn index a0e6afbe6be17..04b00cd09f2e6 100644 --- a/testing/dart/observatory/BUILD.gn +++ b/testing/dart/observatory/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//flutter/impeller/tools/impeller.gni") import("//flutter/testing/dart/compile_test.gni") tests = [ @@ -11,6 +12,10 @@ tests = [ "vmservice_methods_test.dart", ] +if (impeller_enable_3d) { + tests += [ "scene_reload_test.dart" ] +} + foreach(test, tests) { compile_flutter_dart_test("compile_$test") { dart_file = test diff --git a/testing/dart/observatory/README.md b/testing/dart/observatory/README.md index 41b57d88d8a8b..b42184e6b0118 100644 --- a/testing/dart/observatory/README.md +++ b/testing/dart/observatory/README.md @@ -2,4 +2,4 @@ Tests in this folder need to be run with the observatory enabled, e.g. to make VM service method calls. The `run_tests.py` script disables the observatory for other tests in the -parent directory. \ No newline at end of file +parent directory. diff --git a/testing/dart/observatory/scene_reload_test.dart b/testing/dart/observatory/scene_reload_test.dart new file mode 100644 index 0000000000000..dc21e7a0ba8c4 --- /dev/null +++ b/testing/dart/observatory/scene_reload_test.dart @@ -0,0 +1,63 @@ +// 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. + +import 'dart:developer' as developer; +import 'dart:typed_data'; +import 'dart:ui'; + +import 'package:litetest/litetest.dart'; +import 'package:vm_service/vm_service.dart' as vms; +import 'package:vm_service/vm_service_io.dart'; + +void main() { + test('ipscenes can be re-initialized', () async { + vms.VmService? vmService; + SceneShader? shader; + try { + final Float64List transform = Float64List(16); + transform[0] = 1.0; // Scale X + transform[5] = 1.0; // Scale Y + transform[10] = 1.0; // Scale Z + transform[12] = 2.0; // Translation X + transform[13] = 6.0; // Translation Y + transform[14] = 6.0; // Translation Z + transform[15] = 1.0; + final SceneNode sceneNode = await SceneNode.fromAsset( + 'flutter_logo.glb.ipscene', + )..setTransform(transform); + shader = sceneNode.sceneShader(); + _use(shader); + + final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); + + if (info.serverUri == null) { + fail('This test must not be run with --disable-observatory.'); + } + + vmService = await vmServiceConnectUri( + 'ws://localhost:${info.serverUri!.port}${info.serverUri!.path}ws', + ); + final vms.VM vm = await vmService.getVM(); + + expect(vm.isolates!.isNotEmpty, true); + for (final vms.IsolateRef isolateRef in vm.isolates!) { + final vms.Response response = await vmService.callServiceExtension( + 'ext.ui.window.reinitializeScene', + isolateId: isolateRef.id, + args: { + 'assetKey': 'flutter_logo.glb.ipscene', + }, + ); + expect(response.type == 'Success', true); + } + } finally { + await vmService?.dispose(); + shader?.dispose(); + } + }); +} + +void _use(Shader shader) { + +} From c27fdb44acbecba9801ecaaa7247776b552cb5d9 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 20:50:14 -0800 Subject: [PATCH 13/24] Only include the scene observatory test if the kernel file is present --- testing/dart/observatory/BUILD.gn | 5 ++++- .../dart/observatory/{ => scene}/scene_reload_test.dart | 0 testing/run_tests.py | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) rename testing/dart/observatory/{ => scene}/scene_reload_test.dart (100%) diff --git a/testing/dart/observatory/BUILD.gn b/testing/dart/observatory/BUILD.gn index 04b00cd09f2e6..22583f4a29d58 100644 --- a/testing/dart/observatory/BUILD.gn +++ b/testing/dart/observatory/BUILD.gn @@ -13,7 +13,10 @@ tests = [ ] if (impeller_enable_3d) { - tests += [ "scene_reload_test.dart" ] + # This test is in a subdirectory to avoid the `run_test.py` glob by default. + # There is a special check to ensure the test's kernel file is present before + # it's added to the list of tests. + tests += [ "scene/scene_reload_test.dart" ] } foreach(test, tests) { diff --git a/testing/dart/observatory/scene_reload_test.dart b/testing/dart/observatory/scene/scene_reload_test.dart similarity index 100% rename from testing/dart/observatory/scene_reload_test.dart rename to testing/dart/observatory/scene/scene_reload_test.dart diff --git a/testing/run_tests.py b/testing/run_tests.py index 875b0ef88ccfb..635480d486c99 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -759,6 +759,14 @@ def gather_dart_tests(build_dir, test_filter): dart_observatory_tests = glob.glob( '%s/observatory/*_test.dart' % dart_tests_dir ) + # Only include the 3D scene observatory test if the kernel file has been built. + # It'll only be built if Impeller Scene's framework integration is enabled. + dart_scene_observatory_tests = '%s/observatory/scene/scene_reload_test.dart' % dart_tests_dir + if os.path.isfile( + os.path.join(build_dir, 'gen', + os.path.basename(dart_scene_observatory_tests) + '.dill')): + dart_observatory_tests += [dart_scene_observatory_tests] + dart_tests = glob.glob('%s/*_test.dart' % dart_tests_dir) if 'release' not in build_dir: From 6216684efb3c6a6de7b12e6be01ac049fe721497 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 21:32:48 -0800 Subject: [PATCH 14/24] Return future from async reload --- lib/ui/experiments/scene.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart index cd6c69b6321a4..4176e0c67f370 100644 --- a/lib/ui/experiments/scene.dart +++ b/lib/ui/experiments/scene.dart @@ -76,7 +76,7 @@ class SceneNode extends NativeFieldWrapperClass1 { static final Map> _ipsceneRegistry = >{}; - static void _reinitializeScene(String assetKey) async { + static Future _reinitializeScene(String assetKey) async { final WeakReference? sceneRef = _ipsceneRegistry == null ? null : _ipsceneRegistry[assetKey]; From 16c0451c1a1feec11de6f5cad4f887529fb957e2 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 22:19:26 -0800 Subject: [PATCH 15/24] Ignore lints in observatory test --- testing/dart/observatory/scene/scene_reload_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/dart/observatory/scene/scene_reload_test.dart b/testing/dart/observatory/scene/scene_reload_test.dart index dc21e7a0ba8c4..d268aea0bab32 100644 --- a/testing/dart/observatory/scene/scene_reload_test.dart +++ b/testing/dart/observatory/scene/scene_reload_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// ignore_for_file: type=lint + import 'dart:developer' as developer; import 'dart:typed_data'; import 'dart:ui'; From ca8303353232138d20f2addf68f1a6d4ebdf11ee Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 23:13:10 -0800 Subject: [PATCH 16/24] Revert "Ignore lints in observatory test" This reverts commit 16c0451c1a1feec11de6f5cad4f887529fb957e2. --- testing/dart/observatory/scene/scene_reload_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/testing/dart/observatory/scene/scene_reload_test.dart b/testing/dart/observatory/scene/scene_reload_test.dart index d268aea0bab32..dc21e7a0ba8c4 100644 --- a/testing/dart/observatory/scene/scene_reload_test.dart +++ b/testing/dart/observatory/scene/scene_reload_test.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// ignore_for_file: type=lint - import 'dart:developer' as developer; import 'dart:typed_data'; import 'dart:ui'; From 4c923822b2e31873050fec602933dc8ba765af54 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 23:13:25 -0800 Subject: [PATCH 17/24] Revert "Only include the scene observatory test if the kernel file is present" This reverts commit c27fdb44acbecba9801ecaaa7247776b552cb5d9. --- testing/dart/observatory/BUILD.gn | 5 +---- .../dart/observatory/{scene => }/scene_reload_test.dart | 0 testing/run_tests.py | 8 -------- 3 files changed, 1 insertion(+), 12 deletions(-) rename testing/dart/observatory/{scene => }/scene_reload_test.dart (100%) diff --git a/testing/dart/observatory/BUILD.gn b/testing/dart/observatory/BUILD.gn index 22583f4a29d58..04b00cd09f2e6 100644 --- a/testing/dart/observatory/BUILD.gn +++ b/testing/dart/observatory/BUILD.gn @@ -13,10 +13,7 @@ tests = [ ] if (impeller_enable_3d) { - # This test is in a subdirectory to avoid the `run_test.py` glob by default. - # There is a special check to ensure the test's kernel file is present before - # it's added to the list of tests. - tests += [ "scene/scene_reload_test.dart" ] + tests += [ "scene_reload_test.dart" ] } foreach(test, tests) { diff --git a/testing/dart/observatory/scene/scene_reload_test.dart b/testing/dart/observatory/scene_reload_test.dart similarity index 100% rename from testing/dart/observatory/scene/scene_reload_test.dart rename to testing/dart/observatory/scene_reload_test.dart diff --git a/testing/run_tests.py b/testing/run_tests.py index 635480d486c99..875b0ef88ccfb 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -759,14 +759,6 @@ def gather_dart_tests(build_dir, test_filter): dart_observatory_tests = glob.glob( '%s/observatory/*_test.dart' % dart_tests_dir ) - # Only include the 3D scene observatory test if the kernel file has been built. - # It'll only be built if Impeller Scene's framework integration is enabled. - dart_scene_observatory_tests = '%s/observatory/scene/scene_reload_test.dart' % dart_tests_dir - if os.path.isfile( - os.path.join(build_dir, 'gen', - os.path.basename(dart_scene_observatory_tests) + '.dill')): - dart_observatory_tests += [dart_scene_observatory_tests] - dart_tests = glob.glob('%s/*_test.dart' % dart_tests_dir) if 'release' not in build_dir: From e2ffa6a65711da5ded6e3f16b8585a967b85f2d6 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sat, 7 Jan 2023 23:14:14 -0800 Subject: [PATCH 18/24] Revert "Add scene reload test" This reverts commit 50967f03fa114c33443f964028d88ecb45e67873. --- lib/ui/BUILD.gn | 4 -- testing/dart/observatory/BUILD.gn | 5 -- testing/dart/observatory/README.md | 2 +- .../dart/observatory/scene_reload_test.dart | 63 ------------------- 4 files changed, 1 insertion(+), 73 deletions(-) delete mode 100644 testing/dart/observatory/scene_reload_test.dart diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 549713470df27..adaec644f017b 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -216,10 +216,6 @@ if (enable_unittests) { "fixtures/FontManifest.json", "//flutter/third_party/txt/third_party/fonts/Roboto-Medium.ttf", ] - - if (impeller_enable_3d) { - deps += [ "//flutter/impeller/fixtures:scene_fixtures" ] - } } executable("ui_benchmarks") { diff --git a/testing/dart/observatory/BUILD.gn b/testing/dart/observatory/BUILD.gn index 04b00cd09f2e6..a0e6afbe6be17 100644 --- a/testing/dart/observatory/BUILD.gn +++ b/testing/dart/observatory/BUILD.gn @@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//flutter/impeller/tools/impeller.gni") import("//flutter/testing/dart/compile_test.gni") tests = [ @@ -12,10 +11,6 @@ tests = [ "vmservice_methods_test.dart", ] -if (impeller_enable_3d) { - tests += [ "scene_reload_test.dart" ] -} - foreach(test, tests) { compile_flutter_dart_test("compile_$test") { dart_file = test diff --git a/testing/dart/observatory/README.md b/testing/dart/observatory/README.md index b42184e6b0118..41b57d88d8a8b 100644 --- a/testing/dart/observatory/README.md +++ b/testing/dart/observatory/README.md @@ -2,4 +2,4 @@ Tests in this folder need to be run with the observatory enabled, e.g. to make VM service method calls. The `run_tests.py` script disables the observatory for other tests in the -parent directory. +parent directory. \ No newline at end of file diff --git a/testing/dart/observatory/scene_reload_test.dart b/testing/dart/observatory/scene_reload_test.dart deleted file mode 100644 index dc21e7a0ba8c4..0000000000000 --- a/testing/dart/observatory/scene_reload_test.dart +++ /dev/null @@ -1,63 +0,0 @@ -// 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. - -import 'dart:developer' as developer; -import 'dart:typed_data'; -import 'dart:ui'; - -import 'package:litetest/litetest.dart'; -import 'package:vm_service/vm_service.dart' as vms; -import 'package:vm_service/vm_service_io.dart'; - -void main() { - test('ipscenes can be re-initialized', () async { - vms.VmService? vmService; - SceneShader? shader; - try { - final Float64List transform = Float64List(16); - transform[0] = 1.0; // Scale X - transform[5] = 1.0; // Scale Y - transform[10] = 1.0; // Scale Z - transform[12] = 2.0; // Translation X - transform[13] = 6.0; // Translation Y - transform[14] = 6.0; // Translation Z - transform[15] = 1.0; - final SceneNode sceneNode = await SceneNode.fromAsset( - 'flutter_logo.glb.ipscene', - )..setTransform(transform); - shader = sceneNode.sceneShader(); - _use(shader); - - final developer.ServiceProtocolInfo info = await developer.Service.getInfo(); - - if (info.serverUri == null) { - fail('This test must not be run with --disable-observatory.'); - } - - vmService = await vmServiceConnectUri( - 'ws://localhost:${info.serverUri!.port}${info.serverUri!.path}ws', - ); - final vms.VM vm = await vmService.getVM(); - - expect(vm.isolates!.isNotEmpty, true); - for (final vms.IsolateRef isolateRef in vm.isolates!) { - final vms.Response response = await vmService.callServiceExtension( - 'ext.ui.window.reinitializeScene', - isolateId: isolateRef.id, - args: { - 'assetKey': 'flutter_logo.glb.ipscene', - }, - ); - expect(response.type == 'Success', true); - } - } finally { - await vmService?.dispose(); - shader?.dispose(); - } - }); -} - -void _use(Shader shader) { - -} From b06543ee88c6506dfa37b13a33e77fd3b854f274 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 8 Jan 2023 05:07:17 -0800 Subject: [PATCH 19/24] Fix threading --- display_list/display_list.h | 8 +-- impeller/entity/contents/scene_contents.cc | 2 + lib/ui/dart_ui.cc | 2 +- lib/ui/experiments/scene.dart | 4 +- lib/ui/painting/scene/scene_node.cc | 61 +++++++++++++++++----- 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/display_list/display_list.h b/display_list/display_list.h index 1ee8645960737..8d26950826322 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -91,6 +91,7 @@ namespace flutter { V(SetSkColorSource) \ V(SetImageColorSource) \ V(SetRuntimeEffectColorSource) \ + V(SetSceneColorSource) \ \ V(ClearImageFilter) \ V(SetPodImageFilter) \ @@ -159,12 +160,7 @@ namespace flutter { V(DrawShadowTransparentOccluder) #define DL_OP_TO_ENUM_VALUE(name) k##name, -enum class DisplayListOpType { - FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) -#ifdef IMPELLER_ENABLE_3D - DL_OP_TO_ENUM_VALUE(SetSceneColorSource) -#endif // IMPELLER_ENABLE_3D -}; +enum class DisplayListOpType { FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) }; #undef DL_OP_TO_ENUM_VALUE class Dispatcher; diff --git a/impeller/entity/contents/scene_contents.cc b/impeller/entity/contents/scene_contents.cc index 3a1c0d9264fba..3cc574faf2973 100644 --- a/impeller/entity/contents/scene_contents.cc +++ b/impeller/entity/contents/scene_contents.cc @@ -71,6 +71,8 @@ bool SceneContents::Render(const ContentContext& renderer, TiledTextureContents contents; contents.SetGeometry(GetGeometry()); contents.SetTexture(subpass_target.GetRenderTargetTexture()); + contents.SetMatrix( + Matrix::MakeScale(1 / entity.GetTransformation().GetScale())); return contents.Render(renderer, entity, pass); } diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index 86099f8124135..24af045cec348 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -302,7 +302,7 @@ typedef CanvasPath Path; #ifdef IMPELLER_ENABLE_3D #define FFI_FUNCTION_LIST_3D(V) \ - V(SceneNode::Create, 1) V(SceneShader::Create, 1) + V(SceneNode::Create, 1) V(SceneShader::Create, 2) #define FFI_METHOD_LIST_3D(V) \ V(SceneNode, initFromAsset, 3) \ diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart index 4176e0c67f370..fe99db74ef43f 100644 --- a/lib/ui/experiments/scene.dart +++ b/lib/ui/experiments/scene.dart @@ -149,8 +149,8 @@ class SceneShader extends Shader { _dispose(); } - @FfiNative, Handle)>('SceneShader::Create') - external Float32List _constructor(SceneNode node); + @FfiNative('SceneShader::Create') + external void _constructor(SceneNode node); @FfiNative)>('SceneShader::Dispose') external void _dispose(); diff --git a/lib/ui/painting/scene/scene_node.cc b/lib/ui/painting/scene/scene_node.cc index 5967208c16cf0..4714b433e2398 100644 --- a/lib/ui/painting/scene/scene_node.cc +++ b/lib/ui/painting/scene/scene_node.cc @@ -39,28 +39,61 @@ std::string SceneNode::initFromAsset(const std::string& asset_name, return "Completion callback must be a function."; } - if (!UIDartState::Current()->IsImpellerEnabled()) { + auto dart_state = UIDartState::Current(); + if (!dart_state->IsImpellerEnabled()) { return "3D scenes require the Impeller rendering backend to be enabled."; } - std::shared_ptr asset_manager = UIDartState::Current() - ->platform_configuration() - ->client() - ->GetAssetManager(); + std::shared_ptr asset_manager = + dart_state->platform_configuration()->client()->GetAssetManager(); std::unique_ptr data = asset_manager->GetAsMapping(asset_name); if (data == nullptr) { return std::string("Asset '") + asset_name + std::string("' not found."); } - UIDartState::Current()->GetTaskRunners().GetRasterTaskRunner()->PostTask( - fml::MakeCopyable( - [this, completion_callback_handle, data = std::move(data)]() { - auto& context = - *UIDartState::Current()->GetIOManager()->GetImpellerContext(); - node_ = impeller::scene::Node::MakeFromFlatbuffer( - *data, *context.GetResourceAllocator()); - tonic::DartInvoke(completion_callback_handle, {Dart_TypeVoid()}); - })); + auto& task_runners = dart_state->GetTaskRunners(); + + std::promise> context_promise; + auto impeller_context_promise = context_promise.get_future(); + task_runners.GetIOTaskRunner()->PostTask( + fml::MakeCopyable([promise = std::move(context_promise), + io_manager = dart_state->GetIOManager()]() mutable { + promise.set_value(io_manager ? io_manager->GetImpellerContext() + : nullptr); + })); + + auto persistent_completion_callback = + std::make_unique(dart_state, + completion_callback_handle); + + auto ui_task = fml::MakeCopyable( + [this, callback = std::move(persistent_completion_callback)]( + std::shared_ptr node) mutable { + auto dart_state = callback->dart_state().lock(); + if (!dart_state) { + // The root isolate could have died in the meantime. + return; + } + tonic::DartState::Scope scope(dart_state); + + node_ = std::move(node); + tonic::DartInvoke(callback->Get(), {Dart_TypeVoid()}); + + // callback is associated with the Dart isolate and must be + // deleted on the UI thread. + callback.reset(); + }); + + task_runners.GetRasterTaskRunner()->PostTask( + fml::MakeCopyable([ui_task = std::move(ui_task), task_runners, + impeller_context = impeller_context_promise.get(), + data = std::move(data)]() { + auto node = impeller::scene::Node::MakeFromFlatbuffer( + *data, *impeller_context->GetResourceAllocator()); + + task_runners.GetUITaskRunner()->PostTask( + [ui_task, node = std::move(node)]() { ui_task(node); }); + })); return ""; } From 079aba8585764e0200ac7192b4032635fe6784a8 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 8 Jan 2023 05:21:01 -0800 Subject: [PATCH 20/24] Fix build --- display_list/display_list.cc | 9 +++++++++ display_list/display_list.h | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/display_list/display_list.cc b/display_list/display_list.cc index e343ed365e604..751e16158ae58 100644 --- a/display_list/display_list.cc +++ b/display_list/display_list.cc @@ -184,6 +184,9 @@ void DisplayList::Dispatch(Dispatcher& dispatcher, break; FOR_EACH_DISPLAY_LIST_OP(DL_OP_DISPATCH) +#ifdef IMPELLER_ENABLE_3D + DL_OP_DISPATCH(SetSceneColorSource) +#endif // IMPELLER_ENABLE_3D #undef DL_OP_DISPATCH @@ -209,6 +212,9 @@ void DisplayList::DisposeOps(uint8_t* ptr, uint8_t* end) { break; FOR_EACH_DISPLAY_LIST_OP(DL_OP_DISPOSE) +#ifdef IMPELLER_ENABLE_3D + DL_OP_DISPOSE(SetSceneColorSource) +#endif // IMPELLER_ENABLE_3D #undef DL_OP_DISPOSE @@ -247,6 +253,9 @@ static bool CompareOps(uint8_t* ptrA, break; FOR_EACH_DISPLAY_LIST_OP(DL_OP_EQUALS) +#ifdef IMPELLER_ENABLE_3D + DL_OP_EQUALS(SetSceneColorSource) +#endif // IMPELLER_ENABLE_3D #undef DL_OP_EQUALS diff --git a/display_list/display_list.h b/display_list/display_list.h index 8d26950826322..1ee8645960737 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -91,7 +91,6 @@ namespace flutter { V(SetSkColorSource) \ V(SetImageColorSource) \ V(SetRuntimeEffectColorSource) \ - V(SetSceneColorSource) \ \ V(ClearImageFilter) \ V(SetPodImageFilter) \ @@ -160,7 +159,12 @@ namespace flutter { V(DrawShadowTransparentOccluder) #define DL_OP_TO_ENUM_VALUE(name) k##name, -enum class DisplayListOpType { FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) }; +enum class DisplayListOpType { + FOR_EACH_DISPLAY_LIST_OP(DL_OP_TO_ENUM_VALUE) +#ifdef IMPELLER_ENABLE_3D + DL_OP_TO_ENUM_VALUE(SetSceneColorSource) +#endif // IMPELLER_ENABLE_3D +}; #undef DL_OP_TO_ENUM_VALUE class Dispatcher; From 22c48c62b8f60a0cb3f96bd7943ad6d5f8032c04 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Sun, 8 Jan 2023 07:29:14 -0800 Subject: [PATCH 21/24] Fix setCameraTransform and matrix order --- lib/ui/experiments/scene.dart | 7 +++++++ lib/ui/painting/scene/scene_node.cc | 8 ++++---- lib/ui/painting/scene/scene_shader.cc | 8 ++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/ui/experiments/scene.dart b/lib/ui/experiments/scene.dart index fe99db74ef43f..2b2e477a4c41e 100644 --- a/lib/ui/experiments/scene.dart +++ b/lib/ui/experiments/scene.dart @@ -138,6 +138,10 @@ class SceneShader extends Shader { // ignore: unused_field final String? _debugName; + void setCameraTransform(Float64List matrix4) { + _setCameraTransform(matrix4); + } + /// Releases the native resources held by the [SceneShader]. /// /// After this method is called, calling methods on the shader, or attaching @@ -152,6 +156,9 @@ class SceneShader extends Shader { @FfiNative('SceneShader::Create') external void _constructor(SceneNode node); + @FfiNative, Handle)>('SceneShader::SetCameraTransform') + external void _setCameraTransform(Float64List matrix4); + @FfiNative)>('SceneShader::Dispose') external void _dispose(); } diff --git a/lib/ui/painting/scene/scene_node.cc b/lib/ui/painting/scene/scene_node.cc index 4714b433e2398..cc0b2bae1f04b 100644 --- a/lib/ui/painting/scene/scene_node.cc +++ b/lib/ui/painting/scene/scene_node.cc @@ -101,10 +101,10 @@ std::string SceneNode::initFromAsset(const std::string& asset_name, void SceneNode::initFromTransform(const tonic::Float64List& matrix4) { node_ = std::make_shared(); node_->SetLocalTransform( - impeller::Matrix(matrix4[0], matrix4[4], matrix4[8], matrix4[12], // - matrix4[1], matrix4[5], matrix4[9], matrix4[13], // - matrix4[2], matrix4[6], matrix4[10], matrix4[14], // - matrix4[3], matrix4[7], matrix4[11], matrix4[15])); + impeller::Matrix(matrix4[0], matrix4[1], matrix4[2], matrix4[3], // + matrix4[4], matrix4[5], matrix4[6], matrix4[7], // + matrix4[8], matrix4[9], matrix4[10], matrix4[11], // + matrix4[12], matrix4[13], matrix4[14], matrix4[15])); } void SceneNode::AddChild(Dart_Handle scene_node_handle) { diff --git a/lib/ui/painting/scene/scene_shader.cc b/lib/ui/painting/scene/scene_shader.cc index 1dabe51861122..7f3458447105b 100644 --- a/lib/ui/painting/scene/scene_shader.cc +++ b/lib/ui/painting/scene/scene_shader.cc @@ -41,10 +41,10 @@ void SceneShader::Create(Dart_Handle wrapper, Dart_Handle scene_node_handle) { void SceneShader::SetCameraTransform(const tonic::Float64List& matrix4) { camera_transform_ = - impeller::Matrix(matrix4[0], matrix4[4], matrix4[8], matrix4[12], // - matrix4[1], matrix4[5], matrix4[9], matrix4[13], // - matrix4[2], matrix4[6], matrix4[10], matrix4[14], // - matrix4[3], matrix4[7], matrix4[11], matrix4[15]); + impeller::Matrix(matrix4[0], matrix4[1], matrix4[2], matrix4[3], // + matrix4[4], matrix4[5], matrix4[6], matrix4[7], // + matrix4[8], matrix4[9], matrix4[10], matrix4[11], // + matrix4[12], matrix4[13], matrix4[14], matrix4[15]); } static impeller::Matrix DefaultCameraTransform() { From 805e148c7087a8020e0fb60bd2d0a4777ad2912c Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 9 Jan 2023 16:20:49 -0800 Subject: [PATCH 22/24] Disable parent check --- impeller/scene/node.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/impeller/scene/node.cc b/impeller/scene/node.cc index dcc9b2c213278..7343adb8fa98e 100644 --- a/impeller/scene/node.cc +++ b/impeller/scene/node.cc @@ -287,12 +287,19 @@ Matrix Node::GetGlobalTransform() const { } bool Node::AddChild(std::shared_ptr node) { - // This ensures that cycles are impossible. - if (node->parent_ != nullptr) { - VALIDATION_LOG - << "Cannot add a node as a child which already has a parent."; - return false; - } + // TODO(bdero): Figure out a better paradigm/rules for nodes with multiple + // parents. We should probably disallow this, make deep + // copying of nodes cheap and easy, add mesh instancing, etc. + // Today, the parent link is only used for skin posing, and so + // it's reasonable to not have a check and allow multi-parenting. + // Even still, there should still be some kind of cycle + // prevention/detection, ideally at the protocol level. + // + // if (node->parent_ != nullptr) { + // VALIDATION_LOG + // << "Cannot add a node as a child which already has a parent."; + // return false; + // } node->parent_ = this; children_.push_back(std::move(node)); From e29a7944fe953a279b19630b2cf9768b3f1e582c Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 9 Jan 2023 16:21:13 -0800 Subject: [PATCH 23/24] Add display list test --- impeller/display_list/BUILD.gn | 7 +++++ .../display_list/display_list_unittests.cc | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/impeller/display_list/BUILD.gn b/impeller/display_list/BUILD.gn index 0d58c3c4d5245..7b647a80929a0 100644 --- a/impeller/display_list/BUILD.gn +++ b/impeller/display_list/BUILD.gn @@ -44,4 +44,11 @@ impeller_component("display_list_unittests") { ":display_list", "../playground:playground_test", ] + + if (!defined(defines)) { + defines = [] + } + if (impeller_enable_3d) { + defines += [ "IMPELLER_ENABLE_3D" ] + } } diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index f2b5ac2bb5889..3ce405483022a 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -23,6 +23,7 @@ #include "impeller/geometry/constants.h" #include "impeller/geometry/point.h" #include "impeller/playground/widgets.h" +#include "impeller/scene/node.h" #include "third_party/imgui/imgui.h" #include "third_party/skia/include/core/SkBlurTypes.h" #include "third_party/skia/include/core/SkClipOp.h" @@ -1158,5 +1159,32 @@ TEST_P(DisplayListTest, DrawShapes) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +#ifdef IMPELLER_ENABLE_3D +TEST_P(DisplayListTest, SceneColorSource) { + // Load up the scene. + auto mapping = + flutter::testing::OpenFixtureAsMapping("flutter_logo_baked.glb.ipscene"); + ASSERT_NE(mapping, nullptr); + + std::shared_ptr gltf_scene = + impeller::scene::Node::MakeFromFlatbuffer( + *mapping, *GetContext()->GetResourceAllocator()); + ASSERT_NE(gltf_scene, nullptr); + + flutter::DisplayListBuilder builder; + + auto color_source = std::make_shared( + gltf_scene, + Matrix::MakePerspective(Degrees(45), GetWindowSize(), 0.1, 1000) * + Matrix::MakeLookAt({3, 2, -5}, {0, 0, 0}, {0, 1, 0})); + + flutter::DlPaint paint = flutter::DlPaint().setColorSource(color_source); + + builder.drawPaint(paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} +#endif + } // namespace testing } // namespace impeller From 7877d38ae4c35b53d0a031aa8c799f93e80f7964 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 9 Jan 2023 19:31:08 -0800 Subject: [PATCH 24/24] Fix comment --- lib/ui/painting/scene/scene_shader.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/painting/scene/scene_shader.cc b/lib/ui/painting/scene/scene_shader.cc index 7f3458447105b..55e89a266a26c 100644 --- a/lib/ui/painting/scene/scene_shader.cc +++ b/lib/ui/painting/scene/scene_shader.cc @@ -48,7 +48,7 @@ void SceneShader::SetCameraTransform(const tonic::Float64List& matrix4) { } static impeller::Matrix DefaultCameraTransform() { - // TODO(bdero): There's not way to know what the draw area will be yet, so + // TODO(bdero): There's no way to know what the draw area will be yet, so // make the DlSceneColorSource camera transform optional and // defer this default (or parameterize the camera instead). return impeller::Matrix::MakePerspective(