diff --git a/BUILD.gn b/BUILD.gn index d00ac7c9e234e..33053946e3f53 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -177,7 +177,10 @@ group("unittests") { } if (is_mac || is_linux || is_win) { - public_deps += [ "//flutter/impeller:impeller_unittests" ] + public_deps += [ + "//flutter/impeller:impeller_dart_unittests", + "//flutter/impeller:impeller_unittests", + ] } if (is_mac) { diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index ef64f9d55a748..856c60ae1ff39 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1699,11 +1699,14 @@ 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/gpu.dart + ../../../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/floating_point.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/geometry.dart + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/gpu/context.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/lib/ui/gpu/context.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/hash_codes.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/hooks.dart + ../../../flutter/LICENSE ORIGIN: ../../../flutter/lib/ui/io_manager.cc + ../../../flutter/LICENSE @@ -4342,11 +4345,14 @@ 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/gpu.dart 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/floating_point.h FILE: ../../../flutter/lib/ui/geometry.dart +FILE: ../../../flutter/lib/ui/gpu/context.cc +FILE: ../../../flutter/lib/ui/gpu/context.h FILE: ../../../flutter/lib/ui/hash_codes.dart FILE: ../../../flutter/lib/ui/hooks.dart FILE: ../../../flutter/lib/ui/io_manager.cc diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index 91240dd6c151c..a025ba660632c 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui'; +import 'dart:ui' as ui; +//import 'dart:gpu'; void main() {} diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn index 67bf32d03da3f..ec516cd56829c 100644 --- a/impeller/renderer/BUILD.gn +++ b/impeller/renderer/BUILD.gn @@ -160,6 +160,6 @@ impeller_component("renderer_dart_unittests") { "../playground:playground_test", "//flutter/runtime:runtime", "//flutter/testing:fixture_test", - "//flutter/testing:testing_lib", + "//flutter/testing:testing", ] } diff --git a/impeller/renderer/renderer_dart_unittests.cc b/impeller/renderer/renderer_dart_unittests.cc index 2700fa4c23b41..defec38eab2e2 100644 --- a/impeller/renderer/renderer_dart_unittests.cc +++ b/impeller/renderer/renderer_dart_unittests.cc @@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#define FML_USED_ON_EMBEDDER + #include #include "flutter/common/settings.h" #include "flutter/common/task_runners.h" +#include "flutter/fml/backtrace.h" +#include "flutter/fml/command_line.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/runtime/dart_isolate.h" #include "flutter/runtime/dart_vm_lifecycle.h" @@ -21,6 +25,7 @@ #include "impeller/renderer/render_pass.h" #include "impeller/renderer/sampler_library.h" +#include "gtest/gtest.h" #include "third_party/imgui/imgui.h" namespace impeller { @@ -33,7 +38,9 @@ class RendererDartTest : public PlaygroundTest, : settings_(CreateSettingsForFixture()), vm_ref_(flutter::DartVMRef::Create(settings_)) { fml::MessageLoop::EnsureInitializedForCurrentThread(); + current_task_runner_ = fml::MessageLoop::GetCurrent().GetTaskRunner(); + isolate_ = CreateDartIsolate(); assert(isolate_); assert(isolate_->get()->GetPhase() == flutter::DartIsolate::Phase::Running); diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 596dac782b3d4..aae6a6e94a898 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -216,6 +216,12 @@ source_set("ui") { "painting/scene/scene_shader.h", ] + # Experimental "Impeller Dart" API. + sources += [ + "gpu/context.cc", + "gpu/context.h", + ] + deps += [ "//flutter/impeller/scene" ] } } diff --git a/lib/ui/dart_ui.cc b/lib/ui/dart_ui.cc index c32420065eaf7..77b126d797346 100644 --- a/lib/ui/dart_ui.cc +++ b/lib/ui/dart_ui.cc @@ -12,6 +12,7 @@ #include "flutter/lib/ui/compositing/scene.h" #include "flutter/lib/ui/compositing/scene_builder.h" #include "flutter/lib/ui/dart_runtime_hooks.h" +#include "flutter/lib/ui/gpu/context.h" #include "flutter/lib/ui/isolate_name_server/isolate_name_server_natives.h" #include "flutter/lib/ui/painting/canvas.h" #include "flutter/lib/ui/painting/codec.h" @@ -315,6 +316,10 @@ typedef CanvasPath Path; V(SceneShader, SetCameraTransform, 2) \ V(SceneShader, Dispose, 1) +#define FFI_FUNCTION_LIST_GPU(V) V(GpuContext::InitializeDefault, 1) + +#define FFI_METHOD_LIST_GPU(V) + #endif // IMPELLER_ENABLE_3D #define FFI_FUNCTION_INSERT(FUNCTION, ARGS) \ @@ -343,9 +348,13 @@ void* ResolveFfiNativeFunction(const char* name, uintptr_t args) { void InitDispatcherMap() { FFI_FUNCTION_LIST(FFI_FUNCTION_INSERT) FFI_METHOD_LIST(FFI_METHOD_INSERT) + #ifdef IMPELLER_ENABLE_3D FFI_FUNCTION_LIST_3D(FFI_FUNCTION_INSERT) FFI_METHOD_LIST_3D(FFI_METHOD_INSERT) + + FFI_FUNCTION_LIST_GPU(FFI_FUNCTION_INSERT) + FFI_METHOD_LIST_GPU(FFI_METHOD_INSERT) #endif // IMPELLER_ENABLE_3D } diff --git a/lib/ui/experiments/gpu.dart b/lib/ui/experiments/gpu.dart new file mode 100644 index 0000000000000..282f955e6658e --- /dev/null +++ b/lib/ui/experiments/gpu.dart @@ -0,0 +1,184 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +part of dart.ui; + +class GpuContextException implements Exception { + GpuContextException(this.message); + String message; + + @override + String toString() { + return 'GpuContextException: $message'; + } +} + +enum BlendOperation { add, subtract, reverseSubtract } + +enum BlendFactor { + zero, + one, + sourceColor, + oneMinusSourceColor, + sourceAlpha, + oneMinusSourceAlpha, + destinationColor, + oneMinusDestinationColor, + destinationAlpha, + oneMinusDestinationAlpha, + sourceAlphaSaturated, + blendColor, + oneMinusBlendColor, + blendAlpha, + oneMinusBlendAlpha, +} + +class BlendOptions { + const BlendOptions({ + this.colorOperation = BlendOperation.add, + this.sourceColorFactor = BlendFactor.one, + this.destinationColorFactor = BlendFactor.oneMinusSourceAlpha, + this.alphaOperation = BlendOperation.add, + this.sourceAlphaFactor = BlendFactor.one, + this.destinationAlphaFactor = BlendFactor.oneMinusSourceAlpha, + }); + + final BlendOperation colorOperation; + final BlendFactor sourceColorFactor; + final BlendFactor destinationColorFactor; + final BlendOperation alphaOperation; + final BlendFactor sourceAlphaFactor; + final BlendFactor destinationAlphaFactor; +} + +enum StencilOperation { + keep, + zero, + setToReferenceValue, + incrementClamp, + decrementClamp, + invert, + incrementWrap, + decrementWrap, +} + +enum CompareFunction { + never, + always, + less, + equal, + lessEqual, + greater, + notEqual, + greaterEqual, +} + +class StencilOptions { + const StencilOptions({ + this.operation = StencilOperation.incrementClamp, + this.compare = CompareFunction.always, + }); + + final StencilOperation operation; + final CompareFunction compare; +} + +enum ShaderType { + unknown, + voidType, + booleanType, + signedByteType, + unsignedByteType, + signedShortType, + unsignedShortType, + signedIntType, + unsignedIntType, + signedInt64Type, + unsignedInt64Type, + atomicCounterType, + halfFloatType, + floatType, + doubleType, + structType, + imageType, + sampledImageType, + samplerType, +} + +class VertexAttribute { + const VertexAttribute({ + this.name = '', + this.location = 0, + this.set = 0, + this.binding = 0, + this.type = ShaderType.floatType, + this.elements = 2, + }); + + final String name; + final int location; + final int set; + final int binding; + final ShaderType type; + final int elements; +} + +class UniformSlot { + const UniformSlot({ + this.name = '', + this.set = 0, + this.extRes0 = 0, + this.binding = 0, + }); + + final String name; + final int set; + final int extRes0; + final int binding; +} + +class GpuShader {} + +class RasterPipeline {} + +/// A handle to a graphics context. Used to create and manage GPU resources. +/// +/// To obtain the default graphics context, use [getGpuContext]. +class GpuContext extends NativeFieldWrapperClass1 { + /// Creates a new graphics context that corresponds to the default Impeller + /// context. + GpuContext._createDefault() { + final String error = _initializeDefault(); + if (error.isNotEmpty) { + throw GpuContextException(error); + } + } + + //registerShaderLibrary() async + + Future createRasterPipeline({ + required GpuShader vertex, + required GpuShader fragment, + BlendOptions blendOptions = const BlendOptions(), + StencilOptions stencilOptions = const StencilOptions(), + List vertexLayout = const [], + List uniformLayout = const [], + }) async { + return RasterPipeline(); + } + + /// Associates the default Impeller context with this GpuContext. + @Native(symbol: 'GpuContext::InitializeDefault') + external String _initializeDefault(); +} + +GpuContext? _defaultGpuContext; + +/// Returns the default graphics context. +GpuContext getGpuContext() { + _defaultGpuContext ??= GpuContext._createDefault(); + return _defaultGpuContext!; +} diff --git a/lib/ui/experiments/ui.dart b/lib/ui/experiments/ui.dart index 41d3fcfece6c4..70a9ad2faccf9 100644 --- a/lib/ui/experiments/ui.dart +++ b/lib/ui/experiments/ui.dart @@ -37,8 +37,10 @@ part '../painting.dart'; part '../platform_dispatcher.dart'; part '../plugins.dart'; part '../pointer.dart'; -part 'scene.dart'; part '../semantics.dart'; part 'setup_hooks.dart'; part '../text.dart'; part '../window.dart'; + +part 'gpu.dart'; +part 'scene.dart'; diff --git a/lib/ui/gpu/context.cc b/lib/ui/gpu/context.cc new file mode 100644 index 0000000000000..c61b4d2e6c8a2 --- /dev/null +++ b/lib/ui/gpu/context.cc @@ -0,0 +1,54 @@ +// 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/gpu/context.h" + +#include +#include + +#include "flutter/fml/log_level.h" +#include "flutter/fml/logging.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/fml/memory/ref_ptr.h" +#include "flutter/lib/ui/ui_dart_state.h" +#include "third_party/tonic/dart_wrappable.h" + +namespace flutter { + +IMPLEMENT_WRAPPERTYPEINFO(ui, GpuContext); + +std::string GpuContext::InitializeDefault(Dart_Handle wrapper) { + auto dart_state = UIDartState::Current(); + if (!dart_state->IsImpellerEnabled()) { + return "The GpuContext API requires the Impeller rendering backend to be " + "enabled."; + } + + // Grab the Impeller context from the IO manager. + + std::promise> context_promise; + auto impeller_context_future = context_promise.get_future(); + dart_state->GetTaskRunners().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 impeller_context = impeller_context_future.get(); + if (!impeller_context) { + return "Unable to retrieve the Impeller context."; + } + auto res = fml::MakeRefCounted(impeller_context); + res->AssociateWithDartWrapper(wrapper); + + return ""; +} + +GpuContext::GpuContext(std::shared_ptr context) + : context_(std::move(context)) {} + +GpuContext::~GpuContext() = default; + +} // namespace flutter diff --git a/lib/ui/gpu/context.h b/lib/ui/gpu/context.h new file mode 100644 index 0000000000000..5d9056bdb3c72 --- /dev/null +++ b/lib/ui/gpu/context.h @@ -0,0 +1,37 @@ +// 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_GPU_H_ +#define FLUTTER_LIB_UI_GPU_H_ + +#include + +#include "flutter/fml/macros.h" +#include "flutter/fml/memory/ref_counted.h" +#include "flutter/lib/ui/dart_wrapper.h" +#include "impeller/renderer/context.h" +#include "third_party/tonic/dart_library_natives.h" +#include "third_party/tonic/dart_wrappable.h" + +namespace flutter { + +class GpuContext : public RefCountedDartWrappable { + DEFINE_WRAPPERTYPEINFO(); + FML_FRIEND_MAKE_REF_COUNTED(GpuContext); + + public: + explicit GpuContext(std::shared_ptr context); + ~GpuContext() override; + + static std::string InitializeDefault(Dart_Handle wrapper); + + private: + std::shared_ptr context_; + + FML_DISALLOW_COPY_AND_ASSIGN(GpuContext); +}; + +} // namespace flutter + +#endif // FLUTTER_LIB_UI_GPU_H_