diff --git a/engine/src/flutter/BUILD.gn b/engine/src/flutter/BUILD.gn index ac8d81872d1..6d096a5aaff 100644 --- a/engine/src/flutter/BUILD.gn +++ b/engine/src/flutter/BUILD.gn @@ -210,6 +210,7 @@ group("unittests") { public_deps += [ "//flutter/impeller:impeller_dart_unittests", "//flutter/impeller:impeller_unittests", + "//flutter/impeller/toolkit/interop:example", ] } diff --git a/engine/src/flutter/ci/licenses_golden/excluded_files b/engine/src/flutter/ci/licenses_golden/excluded_files index 02aa416fcd9..ff00b35ce92 100644 --- a/engine/src/flutter/ci/licenses_golden/excluded_files +++ b/engine/src/flutter/ci/licenses_golden/excluded_files @@ -219,6 +219,8 @@ ../../../flutter/impeller/toolkit/android/README.md ../../../flutter/impeller/toolkit/android/toolkit_android_unittests.cc ../../../flutter/impeller/toolkit/glvk/README.md +../../../flutter/impeller/toolkit/interop/impeller_unittests.cc +../../../flutter/impeller/toolkit/interop/object_unittests.cc ../../../flutter/impeller/tools/malioc_cores.py ../../../flutter/impeller/tools/malioc_diff.py ../../../flutter/impeller/tools/metal_library.py diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index fdd08c0639c..f6cdc665d47 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -43283,6 +43283,40 @@ ORIGIN: ../../../flutter/impeller/toolkit/glvk/proc_table.cc + ../../../flutter/ ORIGIN: ../../../flutter/impeller/toolkit/glvk/proc_table.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/glvk/trampoline.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/glvk/trampoline.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/color_filter.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/color_filter.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/color_source.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/color_source.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/context.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/context.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/dl.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/dl.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/dl_builder.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/dl_builder.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/example.c + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/formats.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/formats.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/image_filter.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/image_filter.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller_c.c + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/mask_filter.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/mask_filter.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/object.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/object.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/paint.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/paint.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/path.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/path.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/path_builder.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/path_builder.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/playground_test.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/playground_test.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/surface.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/surface.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/texture.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/texture.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/typographer/backends/skia/typeface_skia.cc + ../../../flutter/LICENSE @@ -46127,6 +46161,40 @@ FILE: ../../../flutter/impeller/toolkit/glvk/proc_table.cc FILE: ../../../flutter/impeller/toolkit/glvk/proc_table.h FILE: ../../../flutter/impeller/toolkit/glvk/trampoline.cc FILE: ../../../flutter/impeller/toolkit/glvk/trampoline.h +FILE: ../../../flutter/impeller/toolkit/interop/color_filter.cc +FILE: ../../../flutter/impeller/toolkit/interop/color_filter.h +FILE: ../../../flutter/impeller/toolkit/interop/color_source.cc +FILE: ../../../flutter/impeller/toolkit/interop/color_source.h +FILE: ../../../flutter/impeller/toolkit/interop/context.cc +FILE: ../../../flutter/impeller/toolkit/interop/context.h +FILE: ../../../flutter/impeller/toolkit/interop/dl.cc +FILE: ../../../flutter/impeller/toolkit/interop/dl.h +FILE: ../../../flutter/impeller/toolkit/interop/dl_builder.cc +FILE: ../../../flutter/impeller/toolkit/interop/dl_builder.h +FILE: ../../../flutter/impeller/toolkit/interop/example.c +FILE: ../../../flutter/impeller/toolkit/interop/formats.cc +FILE: ../../../flutter/impeller/toolkit/interop/formats.h +FILE: ../../../flutter/impeller/toolkit/interop/image_filter.cc +FILE: ../../../flutter/impeller/toolkit/interop/image_filter.h +FILE: ../../../flutter/impeller/toolkit/interop/impeller.cc +FILE: ../../../flutter/impeller/toolkit/interop/impeller.h +FILE: ../../../flutter/impeller/toolkit/interop/impeller_c.c +FILE: ../../../flutter/impeller/toolkit/interop/mask_filter.cc +FILE: ../../../flutter/impeller/toolkit/interop/mask_filter.h +FILE: ../../../flutter/impeller/toolkit/interop/object.cc +FILE: ../../../flutter/impeller/toolkit/interop/object.h +FILE: ../../../flutter/impeller/toolkit/interop/paint.cc +FILE: ../../../flutter/impeller/toolkit/interop/paint.h +FILE: ../../../flutter/impeller/toolkit/interop/path.cc +FILE: ../../../flutter/impeller/toolkit/interop/path.h +FILE: ../../../flutter/impeller/toolkit/interop/path_builder.cc +FILE: ../../../flutter/impeller/toolkit/interop/path_builder.h +FILE: ../../../flutter/impeller/toolkit/interop/playground_test.cc +FILE: ../../../flutter/impeller/toolkit/interop/playground_test.h +FILE: ../../../flutter/impeller/toolkit/interop/surface.cc +FILE: ../../../flutter/impeller/toolkit/interop/surface.h +FILE: ../../../flutter/impeller/toolkit/interop/texture.cc +FILE: ../../../flutter/impeller/toolkit/interop/texture.h FILE: ../../../flutter/impeller/tools/malioc.json FILE: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.cc FILE: ../../../flutter/impeller/typographer/backends/skia/text_frame_skia.h diff --git a/engine/src/flutter/impeller/BUILD.gn b/engine/src/flutter/impeller/BUILD.gn index 6ad39ba532e..265a79def86 100644 --- a/engine/src/flutter/impeller/BUILD.gn +++ b/engine/src/flutter/impeller/BUILD.gn @@ -65,6 +65,7 @@ impeller_component("impeller_unittests") { "runtime_stage:runtime_stage_unittests", "shader_archive:shader_archive_unittests", "tessellator:tessellator_unittests", + "toolkit/interop:interop_unittests", ] if (impeller_supports_rendering) { diff --git a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc index 70d630b8028..d4138d111e9 100644 --- a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc +++ b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.cc @@ -127,19 +127,7 @@ ShaderLibraryMappingsForPlayground() { // |PlaygroundImpl| std::shared_ptr PlaygroundImplGLES::GetContext() const { - auto resolver = use_angle_ ? [](const char* name) -> void* { - void* symbol = nullptr; -#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE - void* angle_glesv2 = dlopen("libGLESv2.dylib", RTLD_LAZY); - symbol = dlsym(angle_glesv2, name); -#endif - FML_CHECK(symbol); - return symbol; - } - : [](const char* name) -> void* { - return reinterpret_cast(::glfwGetProcAddress(name)); - }; - auto gl = std::make_unique(resolver); + auto gl = std::make_unique(CreateGLProcAddressResolver()); if (!gl->IsValid()) { FML_LOG(ERROR) << "Proc table when creating a playground was invalid."; return nullptr; @@ -160,6 +148,23 @@ std::shared_ptr PlaygroundImplGLES::GetContext() const { return context; } +// |PlaygroundImpl| +Playground::GLProcAddressResolver +PlaygroundImplGLES::CreateGLProcAddressResolver() const { + return use_angle_ ? [](const char* name) -> void* { + void* symbol = nullptr; +#if IMPELLER_PLAYGROUND_SUPPORTS_ANGLE + void* angle_glesv2 = dlopen("libGLESv2.dylib", RTLD_LAZY); + symbol = dlsym(angle_glesv2, name); +#endif + FML_CHECK(symbol); + return symbol; + } + : [](const char* name) -> void* { + return reinterpret_cast(::glfwGetProcAddress(name)); + }; +} + // |PlaygroundImpl| PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() const { return handle_.get(); diff --git a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h index d5a666f5809..c1973e92941 100644 --- a/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h +++ b/engine/src/flutter/impeller/playground/backend/gles/playground_impl_gles.h @@ -38,6 +38,10 @@ class PlaygroundImplGLES final : public PlaygroundImpl { std::unique_ptr AcquireSurfaceFrame( std::shared_ptr context) override; + // |PlaygroundImpl| + Playground::GLProcAddressResolver CreateGLProcAddressResolver() + const override; + PlaygroundImplGLES(const PlaygroundImplGLES&) = delete; PlaygroundImplGLES& operator=(const PlaygroundImplGLES&) = delete; diff --git a/engine/src/flutter/impeller/playground/playground.cc b/engine/src/flutter/impeller/playground/playground.cc index 80373a4c81c..0989d39b601 100644 --- a/engine/src/flutter/impeller/playground/playground.cc +++ b/engine/src/flutter/impeller/playground/playground.cc @@ -513,4 +513,9 @@ bool Playground::WillRenderSomething() const { return switches_.enable_playground; } +Playground::GLProcAddressResolver Playground::CreateGLProcAddressResolver() + const { + return impl_->CreateGLProcAddressResolver(); +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/playground/playground.h b/engine/src/flutter/impeller/playground/playground.h index 0a3ed68f15d..9bf16f2e957 100644 --- a/engine/src/flutter/impeller/playground/playground.h +++ b/engine/src/flutter/impeller/playground/playground.h @@ -114,6 +114,9 @@ class Playground { /// Returns true if `OpenPlaygroundHere` will actually render anything. bool WillRenderSomething() const; + using GLProcAddressResolver = std::function; + GLProcAddressResolver CreateGLProcAddressResolver() const; + protected: const PlaygroundSwitches switches_; diff --git a/engine/src/flutter/impeller/playground/playground_impl.cc b/engine/src/flutter/impeller/playground/playground_impl.cc index 5abee6e07e2..b9a8ff62813 100644 --- a/engine/src/flutter/impeller/playground/playground_impl.cc +++ b/engine/src/flutter/impeller/playground/playground_impl.cc @@ -66,4 +66,9 @@ Vector2 PlaygroundImpl::GetContentScale() const { return scale; } +Playground::GLProcAddressResolver PlaygroundImpl::CreateGLProcAddressResolver() + const { + return nullptr; +} + } // namespace impeller diff --git a/engine/src/flutter/impeller/playground/playground_impl.h b/engine/src/flutter/impeller/playground/playground_impl.h index 9bab57441a3..35e39881c68 100644 --- a/engine/src/flutter/impeller/playground/playground_impl.h +++ b/engine/src/flutter/impeller/playground/playground_impl.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_IMPL_H_ #define FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_IMPL_H_ +#include #include #include "impeller/playground/playground.h" @@ -35,6 +36,8 @@ class PlaygroundImpl { virtual fml::Status SetCapabilities( const std::shared_ptr& capabilities) = 0; + virtual Playground::GLProcAddressResolver CreateGLProcAddressResolver() const; + protected: const PlaygroundSwitches switches_; diff --git a/engine/src/flutter/impeller/toolkit/interop/BUILD.gn b/engine/src/flutter/impeller/toolkit/interop/BUILD.gn new file mode 100644 index 00000000000..e165701af0a --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/BUILD.gn @@ -0,0 +1,87 @@ +# 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("//flutter/impeller/tools/impeller.gni") + +impeller_component("interop_public") { + public = [ "impeller.h" ] + + sources = [ "impeller_c.c" ] +} + +impeller_component("interop") { + sources = [ + "color_filter.cc", + "color_filter.h", + "color_source.cc", + "color_source.h", + "context.cc", + "context.h", + "dl.cc", + "dl.h", + "dl_builder.cc", + "dl_builder.h", + "formats.cc", + "formats.h", + "image_filter.cc", + "image_filter.h", + "impeller.cc", + "mask_filter.cc", + "mask_filter.h", + "object.cc", + "object.h", + "paint.cc", + "paint.h", + "path.cc", + "path.h", + "path_builder.cc", + "path_builder.h", + "surface.cc", + "surface.h", + "texture.cc", + "texture.h", + ] + + public_deps = [ ":interop_public" ] + + deps = [ + "../../base", + "../../display_list", + "../../entity", + "../../renderer/backend", + "//flutter/display_list", + "//flutter/fml", + ] +} + +impeller_component("example") { + target_type = "executable" + + output_name = "impeller_interop_example" + + sources = [ "example.c" ] + + deps = [ + ":interop", + "//flutter/third_party/glfw", + ] +} + +impeller_component("interop_unittests") { + testonly = true + + sources = [ + "impeller_unittests.cc", + "object_unittests.cc", + "playground_test.cc", + "playground_test.h", + ] + + deps = [ + ":interop", + "../../fixtures", + "../../playground:playground_test", + "//flutter/testing:testing_lib", + ] +} diff --git a/engine/src/flutter/impeller/toolkit/interop/color_filter.cc b/engine/src/flutter/impeller/toolkit/interop/color_filter.cc new file mode 100644 index 00000000000..7e5b2da2b26 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/color_filter.cc @@ -0,0 +1,36 @@ +// 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 "impeller/toolkit/interop/color_filter.h" + +namespace impeller::interop { + +ScopedObject ColorFilter::MakeBlend(Color color, BlendMode mode) { + auto filter = flutter::DlBlendColorFilter::Make(ToDisplayListType(color), + ToDisplayListType(mode)); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +ScopedObject ColorFilter::MakeMatrix(const float matrix[20]) { + auto filter = flutter::DlMatrixColorFilter::Make(matrix); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +ColorFilter::ColorFilter(std::shared_ptr filter) + : filter_(std::move(filter)) {} + +ColorFilter::~ColorFilter() = default; + +const std::shared_ptr& ColorFilter::GetColorFilter() + const { + return filter_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/color_filter.h b/engine/src/flutter/impeller/toolkit/interop/color_filter.h new file mode 100644 index 00000000000..70c0c6ec98c --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/color_filter.h @@ -0,0 +1,39 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_COLOR_FILTER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_COLOR_FILTER_H_ + +#include "flutter/display_list/effects/dl_color_filter.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class ColorFilter final + : public Object { + public: + static ScopedObject MakeBlend(Color color, BlendMode mode); + + static ScopedObject MakeMatrix(const float matrix[20]); + + explicit ColorFilter(std::shared_ptr filter); + + ~ColorFilter() override; + + ColorFilter(const ColorFilter&) = delete; + + ColorFilter& operator=(const ColorFilter&) = delete; + + const std::shared_ptr& GetColorFilter() const; + + private: + std::shared_ptr filter_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_COLOR_FILTER_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/color_source.cc b/engine/src/flutter/impeller/toolkit/interop/color_source.cc new file mode 100644 index 00000000000..23f7ca01f07 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/color_source.cc @@ -0,0 +1,119 @@ +// 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 "impeller/toolkit/interop/color_source.h" + +namespace impeller::interop { + +ScopedObject ColorSource::MakeLinearGradient( + const Point& start_point, + const Point& end_point, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation) { + const auto sk_transformation = ToSkMatrix(transformation); + auto dl_filter = + flutter::DlColorSource::MakeLinear(ToSkiaType(start_point), // + ToSkiaType(end_point), // + stops.size(), // + colors.data(), // + stops.data(), // + tile_mode, // + &sk_transformation // + ); + if (!dl_filter) { + return nullptr; + } + return Create(std::move(dl_filter)); +} + +ScopedObject ColorSource::MakeRadialGradient( + const Point& center, + Scalar radius, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation) { + const auto sk_transformation = ToSkMatrix(transformation); + auto dl_filter = flutter::DlColorSource::MakeRadial(ToSkiaType(center), // + radius, // + stops.size(), // + colors.data(), // + stops.data(), // + tile_mode, // + &sk_transformation // + ); + if (!dl_filter) { + return nullptr; + } + return Create(std::move(dl_filter)); +} + +ScopedObject ColorSource::MakeConicalGradient( + const Point& start_center, + Scalar start_radius, + const Point& end_center, + Scalar end_radius, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation) { + const auto sk_transformation = ToSkMatrix(transformation); + auto dl_filter = + flutter::DlColorSource::MakeConical(ToSkiaType(start_center), // + start_radius, // + ToSkiaType(end_center), // + end_radius, // + stops.size(), // + colors.data(), // + stops.data(), // + tile_mode, // + &sk_transformation // + ); + if (!dl_filter) { + return nullptr; + } + return Create(std::move(dl_filter)); +} + +ScopedObject ColorSource::MakeSweepGradient( + const Point& center, + Scalar start, + Scalar end, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation) { + const auto sk_transformation = ToSkMatrix(transformation); + auto dl_filter = flutter::DlColorSource::MakeSweep(ToSkiaType(center), // + start, // + end, // + stops.size(), // + colors.data(), // + stops.data(), // + tile_mode, // + &sk_transformation // + ); + if (!dl_filter) { + return nullptr; + } + return Create(std::move(dl_filter)); +} + +ColorSource::ColorSource(std::shared_ptr source) + : color_source_(std::move(source)) {} + +ColorSource::~ColorSource() = default; + +bool ColorSource::IsValid() const { + return !!color_source_; +} + +const std::shared_ptr& ColorSource::GetColorSource() + const { + return color_source_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/color_source.h b/engine/src/flutter/impeller/toolkit/interop/color_source.h new file mode 100644 index 00000000000..e588234efc9 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/color_source.h @@ -0,0 +1,77 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_COLOR_SOURCE_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_COLOR_SOURCE_H_ + +#include + +#include "flutter/display_list/effects/dl_color_source.h" +#include "impeller/geometry/color.h" +#include "impeller/geometry/matrix.h" +#include "impeller/geometry/point.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class ColorSource final + : public Object { + public: + static ScopedObject MakeLinearGradient( + const Point& start_point, + const Point& end_point, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation); + + static ScopedObject MakeRadialGradient( + const Point& center, + Scalar radius, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation); + + static ScopedObject MakeConicalGradient( + const Point& start_center, + Scalar start_radius, + const Point& end_center, + Scalar end_radius, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation); + + static ScopedObject MakeSweepGradient( + const Point& center, + Scalar start, + Scalar end, + const std::vector& colors, + const std::vector& stops, + flutter::DlTileMode tile_mode, + const Matrix& transformation); + + explicit ColorSource(std::shared_ptr source); + + ~ColorSource() override; + + ColorSource(const ColorSource&) = delete; + + ColorSource& operator=(const ColorSource&) = delete; + + bool IsValid() const; + + const std::shared_ptr& GetColorSource() const; + + private: + std::shared_ptr color_source_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_COLOR_SOURCE_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/context.cc b/engine/src/flutter/impeller/toolkit/interop/context.cc new file mode 100644 index 00000000000..15e32e25045 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/context.cc @@ -0,0 +1,111 @@ +// 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 "impeller/toolkit/interop/context.h" + +#include + +#include "flutter/fml/logging.h" +#include "impeller/base/validation.h" +#include "impeller/typographer/backends/skia/typographer_context_skia.h" + +#if IMPELLER_ENABLE_OPENGLES +#include "impeller/entity/gles/entity_shaders_gles.h" +#include "impeller/entity/gles/framebuffer_blend_shaders_gles.h" +#include "impeller/renderer/backend/gles/context_gles.h" +#endif // IMPELLER_ENABLE_OPENGLES + +namespace impeller::interop { + +class Context::BackendData { + public: + virtual ~BackendData() = default; +}; + +Context::Context(std::shared_ptr context, + std::shared_ptr backend_data) + : context_(std::move(context), TypographerContextSkia::Make()), + backend_data_(std::move(backend_data)) {} + +Context::~Context() = default; + +bool Context::IsValid() const { + return context_.IsValid(); +} + +std::shared_ptr Context::GetContext() const { + return context_.GetContext(); +} + +#if IMPELLER_ENABLE_OPENGLES + +class ReactorWorker final : public ReactorGLES::Worker, + public Context::BackendData { + public: + ReactorWorker() : thread_id_(std::this_thread::get_id()) {} + + // |ReactorGLES::Worker| + ~ReactorWorker() override = default; + + // |ReactorGLES::Worker| + bool CanReactorReactOnCurrentThreadNow( + const ReactorGLES& reactor) const override { + return thread_id_ == std::this_thread::get_id(); + } + + private: + std::thread::id thread_id_; + + FML_DISALLOW_COPY_AND_ASSIGN(ReactorWorker); +}; + +#endif // IMPELLER_ENABLE_OPENGLES + +ScopedObject Context::CreateOpenGLES( + std::function proc_address_callback) { +#if IMPELLER_ENABLE_OPENGLES + auto proc_table = std::make_unique( + impeller::ProcTableGLES(std::move(proc_address_callback))); + if (!proc_table || !proc_table->IsValid()) { + VALIDATION_LOG << "Could not create valid OpenGL ES proc. table."; + return {}; + } + std::vector> shader_mappings = { + std::make_shared( + impeller_entity_shaders_gles_data, + impeller_entity_shaders_gles_length), + std::make_shared( + impeller_framebuffer_blend_shaders_gles_data, + impeller_framebuffer_blend_shaders_gles_length), + }; + auto impeller_context = + ContextGLES::Create(std::move(proc_table), shader_mappings, false); + if (!impeller_context) { + VALIDATION_LOG << "Could not create Impeller context."; + return {}; + } + auto reactor_worker = std::make_shared(); + auto worker_id = impeller_context->AddReactorWorker(reactor_worker); + if (!worker_id.has_value()) { + VALIDATION_LOG << "Could not add reactor worker."; + return {}; + } + auto context = + Create(std::move(impeller_context), std::move(reactor_worker)); + if (!context->IsValid()) { + VALIDATION_LOG << "Could not create valid context."; + return {}; + } + return context; +#else // IMPELLER_ENABLE_OPENGLES + VALIDATION_LOG << "This build does not support OpenGL ES contexts."; + return {}; +#endif // IMPELLER_ENABLE_OPENGLES +} + +AiksContext& Context::GetAiksContext() { + return context_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/context.h b/engine/src/flutter/impeller/toolkit/interop/context.h new file mode 100644 index 00000000000..2bfb6e4e75b --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/context.h @@ -0,0 +1,47 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_CONTEXT_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_CONTEXT_H_ + +#include + +#include "impeller/aiks/aiks_context.h" +#include "impeller/renderer/context.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class Context final + : public Object { + public: + class BackendData; + + static ScopedObject CreateOpenGLES( + std::function proc_address_callback); + + explicit Context(std::shared_ptr context, + std::shared_ptr backend_data); + + ~Context() override; + + Context(const Context&) = delete; + + Context& operator=(const Context&) = delete; + + bool IsValid() const; + + std::shared_ptr GetContext() const; + + AiksContext& GetAiksContext(); + + private: + impeller::AiksContext context_; + std::shared_ptr backend_data_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_CONTEXT_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/dl.cc b/engine/src/flutter/impeller/toolkit/interop/dl.cc new file mode 100644 index 00000000000..cceee49e30e --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/dl.cc @@ -0,0 +1,22 @@ +// 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 "impeller/toolkit/interop/dl.h" + +namespace impeller::interop { + +DisplayList::DisplayList(sk_sp display_list) + : display_list_(std::move(display_list)) {} + +DisplayList::~DisplayList() = default; + +bool DisplayList::IsValid() const { + return !!display_list_; +} + +const sk_sp DisplayList::GetDisplayList() const { + return display_list_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/dl.h b/engine/src/flutter/impeller/toolkit/interop/dl.h new file mode 100644 index 00000000000..710a0223c75 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/dl.h @@ -0,0 +1,36 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_DL_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_DL_H_ + +#include "flutter/display_list/display_list.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class DisplayList final + : public Object { + public: + explicit DisplayList(sk_sp display_list); + + ~DisplayList() override; + + DisplayList(const DisplayList&) = delete; + + DisplayList& operator=(const DisplayList&) = delete; + + bool IsValid() const; + + const sk_sp GetDisplayList() const; + + private: + sk_sp display_list_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_DL_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/dl_builder.cc b/engine/src/flutter/impeller/toolkit/interop/dl_builder.cc new file mode 100644 index 00000000000..b8547f3c464 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/dl_builder.cc @@ -0,0 +1,179 @@ +// 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 "impeller/toolkit/interop/dl_builder.h" + +#include "impeller/toolkit/interop/formats.h" + +namespace impeller::interop { + +DisplayListBuilder::DisplayListBuilder(const ImpellerRect* rect) + : builder_(ToSkiaType(rect).value_or( + flutter::DisplayListBuilder::kMaxCullRect)) {} + +DisplayListBuilder::~DisplayListBuilder() = default; + +void DisplayListBuilder::Save() { + builder_.Save(); +} + +void DisplayListBuilder::SaveLayer(const Rect& bounds, + const Paint* paint, + const ImageFilter* backdrop) { + const auto sk_bounds = ToSkiaType(bounds); + builder_.SaveLayer( + &sk_bounds, // + paint == nullptr ? nullptr : &paint->GetPaint(), // + backdrop == nullptr ? nullptr : backdrop->GetImageFilter().get()); +} + +void DisplayListBuilder::Restore() { + builder_.Restore(); +} + +void DisplayListBuilder::Scale(Size scale) { + builder_.Scale(scale.width, scale.height); +} + +void DisplayListBuilder::Rotate(Degrees angle) { + builder_.Rotate(angle.degrees); +} + +void DisplayListBuilder::Translate(Point translation) { + builder_.Translate(translation.x, translation.y); +} + +Matrix DisplayListBuilder::GetTransform() const { + Matrix matrix; + builder_.GetTransformFullPerspective().getColMajor(matrix.m); + return matrix; +} + +void DisplayListBuilder::SetTransform(const Matrix& matrix) { + const auto sk_matrix = SkM44::ColMajor(matrix.m); + builder_.SetTransform(&sk_matrix); +} + +void DisplayListBuilder::ResetTransform() { + builder_.TransformReset(); +} + +uint32_t DisplayListBuilder::GetSaveCount() const { + return builder_.GetSaveCount(); +} + +void DisplayListBuilder::RestoreToCount(uint32_t count) { + builder_.RestoreToCount(count); +} + +void DisplayListBuilder::ClipRect(const Rect& rect, + flutter::DlCanvas::ClipOp op) { + builder_.ClipRect(ToSkiaType(rect), op); +} + +void DisplayListBuilder::ClipOval(const Rect& rect, + flutter::DlCanvas::ClipOp op) { + builder_.ClipOval(ToSkiaType(rect), op); +} + +void DisplayListBuilder::ClipRoundedRect( + const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii, + flutter::DlCanvas::ClipOp op) { + builder_.ClipRRect(ToSkiaType(rect, radii), op); +} + +void DisplayListBuilder::ClipPath(const Path& path, + flutter::DlCanvas::ClipOp op) { + builder_.ClipPath(path.GetPath(), op); +} + +void DisplayListBuilder::DrawRect(const Rect& rect, const Paint& paint) { + builder_.DrawRect(ToSkiaType(rect), paint.GetPaint()); +} + +void DisplayListBuilder::DrawOval(const Rect& oval_bounds, const Paint& paint) { + builder_.DrawOval(ToSkiaType(oval_bounds), paint.GetPaint()); +} + +void DisplayListBuilder::DrawRoundedRect( + const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii, + const Paint& paint) { + builder_.DrawRRect(ToSkiaType(rect, radii), paint.GetPaint()); +} + +void DisplayListBuilder::DrawRoundedRectDifference( + const Rect& outer_rect, + const impeller::PathBuilder::RoundingRadii& outer_radii, + const Rect& inner_rect, + const impeller::PathBuilder::RoundingRadii& inner_radii, + const Paint& paint) { + builder_.DrawDRRect(ToSkiaType(outer_rect, outer_radii), // + ToSkiaType(inner_rect, inner_radii), // + paint.GetPaint() // + ); +} + +void DisplayListBuilder::DrawPath(const Path& path, const Paint& paint) { + builder_.DrawPath(path.GetPath(), paint.GetPaint()); +} + +void DisplayListBuilder::DrawPaint(const Paint& paint) { + builder_.DrawPaint(paint.GetPaint()); +} + +void DisplayListBuilder::DrawLine(const Point& from, + const Point& to, + const Paint& paint) { + builder_.DrawLine(ToSkiaType(from), ToSkiaType(to), paint.GetPaint()); +} + +void DisplayListBuilder::DrawDashedLine(const Point& from, + const Point& to, + Scalar on_length, + Scalar off_length, + const Paint& paint) { + builder_.DrawDashedLine(from, // + to, // + on_length, // + off_length, // + paint.GetPaint() // + ); +} + +ScopedObject DisplayListBuilder::Build() { + return Create(builder_.Build()); +} + +void DisplayListBuilder::DrawDisplayList(const DisplayList& dl, + Scalar opacity) { + builder_.DrawDisplayList(dl.GetDisplayList(), opacity); +} + +void DisplayListBuilder::DrawTexture(const Texture& texture, + const Point& point, + flutter::DlImageSampling sampling, + const Paint* paint) { + builder_.DrawImage(texture.MakeImage(), // + ToSkiaType(point), // + sampling, // + paint == nullptr ? nullptr : &paint->GetPaint() // + ); +} + +void DisplayListBuilder::DrawTextureRect(const Texture& texture, + const Rect& src_rect, + const Rect& dst_rect, + flutter::DlImageSampling sampling, + const Paint* paint) { + builder_.DrawImageRect(texture.MakeImage(), // + ToSkiaType(src_rect), // + ToSkiaType(dst_rect), // + sampling, // + paint == nullptr ? nullptr : &paint->GetPaint() // + ); +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/dl_builder.h b/engine/src/flutter/impeller/toolkit/interop/dl_builder.h new file mode 100644 index 00000000000..da790fcff21 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/dl_builder.h @@ -0,0 +1,117 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_DL_BUILDER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_DL_BUILDER_H_ + +#include "flutter/display_list/dl_builder.h" +#include "flutter/display_list/dl_canvas.h" +#include "impeller/geometry/scalar.h" +#include "impeller/geometry/size.h" +#include "impeller/toolkit/interop/dl.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/image_filter.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" +#include "impeller/toolkit/interop/paint.h" +#include "impeller/toolkit/interop/path.h" +#include "impeller/toolkit/interop/texture.h" + +namespace impeller::interop { + +class DisplayListBuilder final + : public Object { + public: + explicit DisplayListBuilder(const ImpellerRect* rect); + + ~DisplayListBuilder() override; + + DisplayListBuilder(const DisplayListBuilder&) = delete; + + DisplayListBuilder& operator=(const DisplayListBuilder&) = delete; + + void Save(); + + void SaveLayer(const Rect& bounds, + const Paint* paint, + const ImageFilter* backdrop); + + void Restore(); + + void Scale(Size scale); + + void Rotate(Degrees angle); + + void Translate(Point translation); + + Matrix GetTransform() const; + + void SetTransform(const Matrix& matrix); + + void ResetTransform(); + + uint32_t GetSaveCount() const; + + void RestoreToCount(uint32_t count); + + void ClipRect(const Rect& rect, flutter::DlCanvas::ClipOp op); + + void ClipOval(const Rect& rect, flutter::DlCanvas::ClipOp op); + + void ClipRoundedRect(const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii, + flutter::DlCanvas::ClipOp op); + + void ClipPath(const Path& path, flutter::DlCanvas::ClipOp op); + + void DrawPaint(const Paint& paint); + + void DrawLine(const Point& from, const Point& to, const Paint& paint); + + void DrawDashedLine(const Point& from, + const Point& to, + Scalar on_length, + Scalar off_length, + const Paint& paint); + + void DrawRect(const Rect& rect, const Paint& paint); + + void DrawOval(const Rect& oval_bounds, const Paint& paint); + + void DrawRoundedRect(const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii, + const Paint& paint); + + void DrawRoundedRectDifference( + const Rect& outer_rect, + const impeller::PathBuilder::RoundingRadii& outer_radii, + const Rect& inner_rect, + const impeller::PathBuilder::RoundingRadii& inner_radii, + const Paint& paint); + + void DrawPath(const Path& path, const Paint& paint); + + void DrawTexture(const Texture& texture, + const Point& point, + flutter::DlImageSampling sampling, + const Paint* paint); + + void DrawTextureRect(const Texture& texture, + const Rect& src_rect, + const Rect& dst_rect, + flutter::DlImageSampling sampling, + const Paint* paint); + + void DrawDisplayList(const DisplayList& dl, Scalar opacity); + + ScopedObject Build(); + + private: + flutter::DisplayListBuilder builder_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_DL_BUILDER_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/example.c b/engine/src/flutter/impeller/toolkit/interop/example.c new file mode 100644 index 00000000000..f121f182fc2 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/example.c @@ -0,0 +1,91 @@ +// 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 +#include + +#include "GLFW/glfw3.h" +#include "impeller.h" + +void GLFWErrorCallback(int error, const char* description) { + // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) + fprintf(stderr, "GLFW Error (%d): %s\n", error, description); + fflush(stderr); +} + +void* ProcAddressCallback(const char* proc_name, void* user_data) { + return glfwGetProcAddress(proc_name); +} + +int main(int argc, char const* argv[]) { + glfwSetErrorCallback(GLFWErrorCallback); + [[maybe_unused]] int result = glfwInit(); + assert(result == GLFW_TRUE); + + glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); + + GLFWwindow* window = + glfwCreateWindow(800, 600, "Impeller Example", NULL, NULL); + assert(window != NULL); + + int framebuffer_width, framebuffer_height; + glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height); + + // The GL context must be current on the calling thread. + glfwMakeContextCurrent(window); + + ImpellerContext context = ImpellerContextCreateOpenGLESNew( + IMPELLER_VERSION, ProcAddressCallback, NULL); + assert(context != NULL); + + ImpellerISize surface_size = {}; + surface_size.width = framebuffer_width; + surface_size.height = framebuffer_height; + + ImpellerSurface surface = ImpellerSurfaceCreateWrappedFBONew( + context, 0u, kImpellerPixelFormatRGBA8888, &surface_size); + assert(surface != NULL); + + ImpellerDisplayList dl = NULL; + + { + ImpellerDisplayListBuilder builder = ImpellerDisplayListBuilderNew(NULL); + ImpellerPaint paint = ImpellerPaintNew(); + + // Clear the background to a white color. + ImpellerColor clear_color = {1.0, 1.0, 1.0, 1.0}; + ImpellerPaintSetColor(paint, &clear_color); + ImpellerDisplayListBuilderDrawPaint(builder, paint); + + // Draw a red box. + ImpellerColor box_color = {1.0, 0.0, 0.0, 1.0}; + ImpellerPaintSetColor(paint, &box_color); + ImpellerRect box_rect = {10, 10, 100, 100}; + ImpellerDisplayListBuilderDrawRect(builder, &box_rect, paint); + + dl = ImpellerDisplayListBuilderCreateDisplayListNew(builder); + + ImpellerPaintRelease(paint); + ImpellerDisplayListBuilderRelease(builder); + } + + assert(dl != NULL); + + while (!glfwWindowShouldClose(window)) { + glfwWaitEvents(); + ImpellerSurfaceDrawDisplayList(surface, dl); + glfwSwapBuffers(window); + } + + ImpellerDisplayListRelease(dl); + ImpellerSurfaceRelease(surface); + ImpellerContextRelease(context); + + glfwMakeContextCurrent(NULL); + + glfwDestroyWindow(window); + + glfwTerminate(); + return 0; +} diff --git a/engine/src/flutter/impeller/toolkit/interop/formats.cc b/engine/src/flutter/impeller/toolkit/interop/formats.cc new file mode 100644 index 00000000000..29b213405da --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/formats.cc @@ -0,0 +1,11 @@ +// 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 "impeller/toolkit/interop/formats.h" + +namespace impeller::interop { + +// + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/formats.h b/engine/src/flutter/impeller/toolkit/interop/formats.h new file mode 100644 index 00000000000..4acd3a73b2e --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/formats.h @@ -0,0 +1,423 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_FORMATS_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_FORMATS_H_ + +#include + +#include "flutter/display_list/dl_builder.h" +#include "flutter/display_list/dl_color.h" +#include "impeller/entity/entity.h" +#include "impeller/geometry/color.h" +#include "impeller/geometry/matrix.h" +#include "impeller/geometry/path_builder.h" +#include "impeller/geometry/point.h" +#include "impeller/geometry/rect.h" +#include "impeller/geometry/size.h" +#include "impeller/toolkit/interop/impeller.h" + +namespace impeller::interop { + +constexpr std::optional ToSkiaType(const ImpellerRect* rect) { + if (!rect) { + return std::nullopt; + } + return SkRect::MakeXYWH(rect->x, rect->y, rect->width, rect->height); +} + +constexpr SkPoint ToSkiaType(const Point& point) { + return SkPoint::Make(point.x, point.y); +} + +constexpr SkRect ToSkiaType(const Rect& rect) { + return SkRect::MakeXYWH(rect.GetX(), // + rect.GetY(), // + rect.GetWidth(), // + rect.GetHeight() // + ); +} + +constexpr SkPathFillType ToSkiaType(FillType type) { + switch (type) { + case FillType::kNonZero: + return SkPathFillType::kWinding; + case FillType::kOdd: + return SkPathFillType::kEvenOdd; + } + return SkPathFillType::kWinding; +} + +constexpr SkIRect ToSkiaType(IRect rect) { + return SkIRect::MakeXYWH(rect.GetX(), // + rect.GetY(), // + rect.GetWidth(), // + rect.GetHeight() // + ); +} + +template +std::vector ToSkiaType(const std::vector& other_vec) { + std::vector skia_vec; + skia_vec.reserve(other_vec.size()); + for (const auto& other : other_vec) { + skia_vec.emplace_back(ToSkiaType(other)); + } + return skia_vec; +} + +constexpr flutter::DlColor ToDisplayListType(Color color) { + return flutter::DlColor::RGBA(color.red, // + color.green, // + color.blue, // + color.alpha // + ); +} + +constexpr SkMatrix ToSkMatrix(const Matrix& matrix) { + return SkM44::ColMajor(matrix.m).asM33(); +} + +template +std::vector ToDisplayListType(const std::vector& other_vec) { + std::vector dl_vec; + dl_vec.reserve(other_vec.size()); + for (const auto& other : other_vec) { + dl_vec.emplace_back(ToDisplayListType(other)); + } + return dl_vec; +} + +constexpr flutter::DlImageSampling ToDisplayListType( + ImpellerTextureSampling sampling) { + switch (sampling) { + case kImpellerTextureSamplingNearestNeighbor: + return flutter::DlImageSampling::kNearestNeighbor; + case kImpellerTextureSamplingLinear: + return flutter::DlImageSampling::kLinear; + } + return flutter::DlImageSampling::kLinear; +} + +constexpr flutter::DlBlurStyle ToDisplayListType(ImpellerBlurStyle style) { + switch (style) { + case kImpellerBlurStyleNormal: + return flutter::DlBlurStyle::kNormal; + case kImpellerBlurStyleSolid: + return flutter::DlBlurStyle::kSolid; + case kImpellerBlurStyleOuter: + return flutter::DlBlurStyle::kOuter; + case kImpellerBlurStyleInner: + return flutter::DlBlurStyle::kInner; + } + return flutter::DlBlurStyle::kNormal; +} + +constexpr flutter::DlBlendMode ToDisplayListType(BlendMode mode) { + using Mode = flutter::DlBlendMode; + switch (mode) { + case BlendMode::kClear: + return Mode::kClear; + case BlendMode::kSource: + return Mode::kSrc; + case BlendMode::kDestination: + return Mode::kDst; + case BlendMode::kSourceOver: + return Mode::kSrcOver; + case BlendMode::kDestinationOver: + return Mode::kDstOver; + case BlendMode::kSourceIn: + return Mode::kSrcIn; + case BlendMode::kDestinationIn: + return Mode::kDstIn; + case BlendMode::kSourceOut: + return Mode::kSrcOut; + case BlendMode::kDestinationOut: + return Mode::kDstOut; + case BlendMode::kSourceATop: + return Mode::kSrcATop; + case BlendMode::kDestinationATop: + return Mode::kDstATop; + case BlendMode::kXor: + return Mode::kXor; + case BlendMode::kPlus: + return Mode::kPlus; + case BlendMode::kModulate: + return Mode::kModulate; + case BlendMode::kScreen: + return Mode::kScreen; + case BlendMode::kOverlay: + return Mode::kOverlay; + case BlendMode::kDarken: + return Mode::kDarken; + case BlendMode::kLighten: + return Mode::kLighten; + case BlendMode::kColorDodge: + return Mode::kColorDodge; + case BlendMode::kColorBurn: + return Mode::kColorBurn; + case BlendMode::kHardLight: + return Mode::kHardLight; + case BlendMode::kSoftLight: + return Mode::kSoftLight; + case BlendMode::kDifference: + return Mode::kDifference; + case BlendMode::kExclusion: + return Mode::kExclusion; + case BlendMode::kMultiply: + return Mode::kMultiply; + case BlendMode::kHue: + return Mode::kHue; + case BlendMode::kSaturation: + return Mode::kSaturation; + case BlendMode::kColor: + return Mode::kColor; + case BlendMode::kLuminosity: + return Mode::kLuminosity; + } + return Mode::kSrcOver; +} + +inline SkRRect ToSkiaType(const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii) { + using Corner = SkRRect::Corner; + SkVector sk_radii[4]; + sk_radii[Corner::kUpperLeft_Corner] = ToSkiaType(radii.top_left); + sk_radii[Corner::kUpperRight_Corner] = ToSkiaType(radii.top_right); + sk_radii[Corner::kLowerRight_Corner] = ToSkiaType(radii.bottom_right); + sk_radii[Corner::kLowerLeft_Corner] = ToSkiaType(radii.bottom_left); + SkRRect result; + result.setRectRadii(ToSkiaType(rect), sk_radii); + return result; +} + +constexpr Matrix ToImpellerType(const ImpellerMatrix& m) { + return Matrix(m.m[0], m.m[1], m.m[2], m.m[3], // + m.m[4], m.m[5], m.m[6], m.m[7], // + m.m[8], m.m[9], m.m[10], m.m[11], // + m.m[12], m.m[13], m.m[14], m.m[15] // + ); +} + +constexpr void FromImpellerType(const Matrix& from, ImpellerMatrix& to) { + to.m[0] = from.m[0]; + to.m[1] = from.m[1]; + to.m[2] = from.m[2]; + to.m[3] = from.m[3]; + to.m[4] = from.m[4]; + to.m[5] = from.m[5]; + to.m[6] = from.m[6]; + to.m[7] = from.m[7]; + to.m[8] = from.m[8]; + to.m[9] = from.m[9]; + to.m[10] = from.m[10]; + to.m[11] = from.m[11]; + to.m[12] = from.m[12]; + to.m[13] = from.m[13]; + to.m[14] = from.m[14]; + to.m[15] = from.m[15]; +} + +constexpr Size ToImpellerType(const ImpellerSize& size) { + return Size{size.width, size.height}; +} + +constexpr Point ToImpellerType(const ImpellerPoint& point) { + return Point{point.x, point.y}; +} + +constexpr Rect ToImpellerType(const ImpellerRect& rect) { + return Rect::MakeXYWH(rect.x, rect.y, rect.width, rect.height); +} + +constexpr flutter::DlTileMode ToDisplayListType(ImpellerTileMode mode) { + switch (mode) { + case kImpellerTileModeClamp: + return flutter::DlTileMode::kClamp; + case kImpellerTileModeRepeat: + return flutter::DlTileMode::kRepeat; + case kImpellerTileModeMirror: + return flutter::DlTileMode::kMirror; + case kImpellerTileModeDecal: + return flutter::DlTileMode::kDecal; + } + return flutter::DlTileMode::kClamp; +} + +constexpr impeller::PathBuilder::RoundingRadii ToImpellerType( + const ImpellerRoundingRadii& radii) { + auto result = impeller::PathBuilder::RoundingRadii{}; + result.top_left = ToImpellerType(radii.top_left); + result.bottom_left = ToImpellerType(radii.bottom_left); + result.top_right = ToImpellerType(radii.top_right); + result.bottom_right = ToImpellerType(radii.bottom_right); + return result; +} + +constexpr FillType ToImpellerType(ImpellerFillType type) { + switch (type) { + case kImpellerFillTypeNonZero: + return FillType::kNonZero; + case kImpellerFillTypeOdd: + return FillType::kOdd; + } + return FillType::kNonZero; +} + +constexpr flutter::DlCanvas::ClipOp ToImpellerType(ImpellerClipOperation op) { + switch (op) { + case kImpellerClipOperationDifference: + return flutter::DlCanvas::ClipOp::kDifference; + case kImpellerClipOperationIntersect: + return flutter::DlCanvas::ClipOp::kIntersect; + } + return flutter::DlCanvas::ClipOp::kDifference; +} + +constexpr Color ToImpellerType(const ImpellerColor& color) { + Color result; + result.red = color.red; + result.green = color.green; + result.blue = color.blue; + result.alpha = color.alpha; + return result; +} + +constexpr BlendMode ToImpellerType(ImpellerBlendMode mode) { + switch (mode) { + case kImpellerBlendModeClear: + return BlendMode::kClear; + case kImpellerBlendModeSource: + return BlendMode::kSource; + case kImpellerBlendModeDestination: + return BlendMode::kDestination; + case kImpellerBlendModeSourceOver: + return BlendMode::kSourceOver; + case kImpellerBlendModeDestinationOver: + return BlendMode::kDestinationOver; + case kImpellerBlendModeSourceIn: + return BlendMode::kSourceIn; + case kImpellerBlendModeDestinationIn: + return BlendMode::kDestinationIn; + case kImpellerBlendModeSourceOut: + return BlendMode::kSourceOut; + case kImpellerBlendModeDestinationOut: + return BlendMode::kDestinationOut; + case kImpellerBlendModeSourceATop: + return BlendMode::kSourceATop; + case kImpellerBlendModeDestinationATop: + return BlendMode::kDestinationATop; + case kImpellerBlendModeXor: + return BlendMode::kXor; + case kImpellerBlendModePlus: + return BlendMode::kPlus; + case kImpellerBlendModeModulate: + return BlendMode::kModulate; + case kImpellerBlendModeScreen: + return BlendMode::kScreen; + case kImpellerBlendModeOverlay: + return BlendMode::kOverlay; + case kImpellerBlendModeDarken: + return BlendMode::kDarken; + case kImpellerBlendModeLighten: + return BlendMode::kLighten; + case kImpellerBlendModeColorDodge: + return BlendMode::kColorDodge; + case kImpellerBlendModeColorBurn: + return BlendMode::kColorBurn; + case kImpellerBlendModeHardLight: + return BlendMode::kHardLight; + case kImpellerBlendModeSoftLight: + return BlendMode::kSoftLight; + case kImpellerBlendModeDifference: + return BlendMode::kDifference; + case kImpellerBlendModeExclusion: + return BlendMode::kExclusion; + case kImpellerBlendModeMultiply: + return BlendMode::kMultiply; + case kImpellerBlendModeHue: + return BlendMode::kHue; + case kImpellerBlendModeSaturation: + return BlendMode::kSaturation; + case kImpellerBlendModeColor: + return BlendMode::kColor; + case kImpellerBlendModeLuminosity: + return BlendMode::kLuminosity; + } + return BlendMode::kSourceOver; +} + +constexpr flutter::DlDrawStyle ToDisplayListType(ImpellerDrawStyle style) { + switch (style) { + case kImpellerDrawStyleFill: + return flutter::DlDrawStyle::kFill; + case kImpellerDrawStyleStroke: + return flutter::DlDrawStyle::kStroke; + case kImpellerDrawStyleStrokeAndFill: + return flutter::DlDrawStyle::kStrokeAndFill; + } + return flutter::DlDrawStyle::kFill; +} + +constexpr flutter::DlStrokeCap ToDisplayListType(ImpellerStrokeCap cap) { + switch (cap) { + case kImpellerStrokeCapButt: + return flutter::DlStrokeCap::kButt; + case kImpellerStrokeCapRound: + return flutter::DlStrokeCap::kRound; + case kImpellerStrokeCapSquare: + return flutter::DlStrokeCap::kSquare; + } + return flutter::DlStrokeCap::kButt; +} + +constexpr flutter::DlStrokeJoin ToDisplayListType(ImpellerStrokeJoin join) { + switch (join) { + case kImpellerStrokeJoinMiter: + return flutter::DlStrokeJoin::kMiter; + case kImpellerStrokeJoinRound: + return flutter::DlStrokeJoin::kRound; + case kImpellerStrokeJoinBevel: + return flutter::DlStrokeJoin::kBevel; + } + return flutter::DlStrokeJoin::kMiter; +} + +constexpr PixelFormat ToImpellerType(ImpellerPixelFormat format) { + switch (format) { + case kImpellerPixelFormatRGBA8888: + return PixelFormat::kR8G8B8A8UNormInt; + } + return PixelFormat::kR8G8B8A8UNormInt; +} + +constexpr ISize ToImpellerType(const ImpellerISize& size) { + return ISize::MakeWH(size.width, size.height); +} + +constexpr flutter::DlColorSpace ToDisplayListType( + ImpellerColorSpace color_space) { + switch (color_space) { + case kImpellerColorSpaceSRGB: + return flutter::DlColorSpace::kSRGB; + case kImpellerColorSpaceExtendedSRGB: + return flutter::DlColorSpace::kExtendedSRGB; + case kImpellerColorSpaceDisplayP3: + return flutter::DlColorSpace::kDisplayP3; + } + return flutter::DlColorSpace::kSRGB; +} + +constexpr flutter::DlColor ToDisplayListType(ImpellerColor color) { + return flutter::DlColor(color.alpha, // + color.red, // + color.green, // + color.blue, // + ToDisplayListType(color.color_space) // + ); +} + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_FORMATS_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/image_filter.cc b/engine/src/flutter/impeller/toolkit/interop/image_filter.cc new file mode 100644 index 00000000000..b5dbf895581 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/image_filter.cc @@ -0,0 +1,68 @@ +// 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 "impeller/toolkit/interop/image_filter.h" + +namespace impeller::interop { + +ImageFilter::ImageFilter(std::shared_ptr filter) + : filter_(std::move(filter)) {} + +ImageFilter::~ImageFilter() = default; + +ScopedObject ImageFilter::MakeBlur(Scalar x_sigma, + Scalar y_sigma, + flutter::DlTileMode tile_mode) { + auto filter = flutter::DlBlurImageFilter::Make(x_sigma, y_sigma, tile_mode); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +ScopedObject ImageFilter::MakeDilate(Scalar x_radius, + Scalar y_radius) { + auto filter = flutter::DlDilateImageFilter::Make(x_radius, y_radius); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +ScopedObject ImageFilter::MakeErode(Scalar x_radius, + Scalar y_radius) { + auto filter = flutter::DlErodeImageFilter::Make(x_radius, y_radius); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +ScopedObject ImageFilter::MakeMatrix( + const Matrix& matrix, + flutter::DlImageSampling sampling) { + auto filter = + flutter::DlMatrixImageFilter::Make(ToSkMatrix(matrix), sampling); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +ScopedObject ImageFilter::MakeCompose(const ImageFilter& outer, + const ImageFilter& inner) { + auto filter = flutter::DlComposeImageFilter::Make(outer.GetImageFilter(), + inner.GetImageFilter()); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +const std::shared_ptr& +ImageFilter::GetImageFilter() const { + return filter_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/image_filter.h b/engine/src/flutter/impeller/toolkit/interop/image_filter.h new file mode 100644 index 00000000000..4c6ae4e9beb --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/image_filter.h @@ -0,0 +1,50 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_IMAGE_FILTER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMAGE_FILTER_H_ + +#include "flutter/display_list/effects/dl_image_filter.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class ImageFilter final + : public Object { + public: + static ScopedObject MakeBlur(Scalar x_sigma, + Scalar y_sigma, + flutter::DlTileMode tile_mode); + + static ScopedObject MakeDilate(Scalar x_radius, Scalar y_radius); + + static ScopedObject MakeErode(Scalar x_radius, Scalar y_radius); + + static ScopedObject MakeMatrix( + const Matrix& matrix, + flutter::DlImageSampling sampling); + + static ScopedObject MakeCompose(const ImageFilter& outer, + const ImageFilter& inner); + + explicit ImageFilter(std::shared_ptr filter); + + ~ImageFilter() override; + + ImageFilter(const ImageFilter&) = delete; + + ImageFilter& operator=(const ImageFilter&) = delete; + + const std::shared_ptr& GetImageFilter() const; + + private: + std::shared_ptr filter_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMAGE_FILTER_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/impeller.cc b/engine/src/flutter/impeller/toolkit/interop/impeller.cc new file mode 100644 index 00000000000..e371d274855 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/impeller.cc @@ -0,0 +1,820 @@ +// 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 "impeller/toolkit/interop/impeller.h" + +#include + +#include "flutter/fml/mapping.h" +#include "impeller/base/validation.h" +#include "impeller/geometry/scalar.h" +#include "impeller/toolkit/interop/color_filter.h" +#include "impeller/toolkit/interop/color_source.h" +#include "impeller/toolkit/interop/context.h" +#include "impeller/toolkit/interop/dl_builder.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/image_filter.h" +#include "impeller/toolkit/interop/mask_filter.h" +#include "impeller/toolkit/interop/object.h" +#include "impeller/toolkit/interop/paint.h" +#include "impeller/toolkit/interop/path.h" +#include "impeller/toolkit/interop/path_builder.h" +#include "impeller/toolkit/interop/surface.h" +#include "impeller/toolkit/interop/texture.h" + +namespace impeller::interop { + +#define DEFINE_PEER_GETTER(cxx_type, c_type) \ + cxx_type* GetPeer(c_type object) { \ + return reinterpret_cast(object); \ + } + +DEFINE_PEER_GETTER(ColorFilter, ImpellerColorFilter); +DEFINE_PEER_GETTER(ColorSource, ImpellerColorSource); +DEFINE_PEER_GETTER(Context, ImpellerContext); +DEFINE_PEER_GETTER(DisplayList, ImpellerDisplayList); +DEFINE_PEER_GETTER(DisplayListBuilder, ImpellerDisplayListBuilder); +DEFINE_PEER_GETTER(ImageFilter, ImpellerImageFilter); +DEFINE_PEER_GETTER(MaskFilter, ImpellerMaskFilter); +DEFINE_PEER_GETTER(Paint, ImpellerPaint); +DEFINE_PEER_GETTER(Path, ImpellerPath); +DEFINE_PEER_GETTER(PathBuilder, ImpellerPathBuilder); +DEFINE_PEER_GETTER(Surface, ImpellerSurface); +DEFINE_PEER_GETTER(Texture, ImpellerTexture); + +static std::string GetVersionAsString(uint32_t version) { + std::stringstream stream; + stream << IMPELLER_VERSION_GET_VARIANT(version) << "." + << IMPELLER_VERSION_GET_MAJOR(version) << "." + << IMPELLER_VERSION_GET_MINOR(version) << "." + << IMPELLER_VERSION_GET_PATCH(version); + return stream.str(); +} + +IMPELLER_EXTERN_C +uint32_t ImpellerGetVersion() { + return IMPELLER_VERSION; +} + +IMPELLER_EXTERN_C +ImpellerContext ImpellerContextCreateOpenGLESNew( + uint32_t version, + ImpellerProcAddressCallback gl_proc_address_callback, + void* gl_proc_address_callback_user_data) { + if (version != IMPELLER_VERSION) { + VALIDATION_LOG << "This version of Impeller (" + << GetVersionAsString(ImpellerGetVersion()) << ") " + << "doesn't match the version the user expects (" + << GetVersionAsString(version) << ")."; + return nullptr; + } + auto context = Context::CreateOpenGLES( + [gl_proc_address_callback, + gl_proc_address_callback_user_data](const char* proc_name) -> void* { + return gl_proc_address_callback(proc_name, + gl_proc_address_callback_user_data); + }); + if (!context || !context->IsValid()) { + VALIDATION_LOG << "Could not create valid context."; + return nullptr; + } + return context.Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerContextRetain(ImpellerContext context) { + ObjectBase::SafeRetain(context); +} + +IMPELLER_EXTERN_C +void ImpellerContextRelease(ImpellerContext context) { + ObjectBase::SafeRelease(context); +} + +IMPELLER_EXTERN_C +ImpellerDisplayListBuilder ImpellerDisplayListBuilderNew( + const ImpellerRect* cull_rect) { + return Create(cull_rect).Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderRetain(ImpellerDisplayListBuilder builder) { + ObjectBase::SafeRetain(builder); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderRelease(ImpellerDisplayListBuilder builder) { + ObjectBase::SafeRelease(builder); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderSave(ImpellerDisplayListBuilder builder) { + GetPeer(builder)->Save(); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderSaveLayer(ImpellerDisplayListBuilder builder, + const ImpellerRect* bounds, + ImpellerPaint paint, + ImpellerImageFilter backdrop) { + GetPeer(builder)->SaveLayer(ToImpellerType(*bounds), // + GetPeer(paint), // + GetPeer(backdrop) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderRestore(ImpellerDisplayListBuilder builder) { + GetPeer(builder)->Restore(); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderScale(ImpellerDisplayListBuilder builder, + float x_scale, + float y_scale) { + GetPeer(builder)->Scale(Size{x_scale, y_scale}); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderRotate(ImpellerDisplayListBuilder builder, + float angle_degrees) { + GetPeer(builder)->Rotate(Degrees{angle_degrees}); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderTranslate(ImpellerDisplayListBuilder builder, + float x_translation, + float y_translation) { + GetPeer(builder)->Translate(Point{x_translation, y_translation}); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderSetTransform(ImpellerDisplayListBuilder builder, + const ImpellerMatrix* transform) { + GetPeer(builder)->SetTransform(ToImpellerType(*transform)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderGetTransform(ImpellerDisplayListBuilder builder, + ImpellerMatrix* out_transform) { + FromImpellerType(GetPeer(builder)->GetTransform(), *out_transform); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderResetTransform( + ImpellerDisplayListBuilder builder) { + GetPeer(builder)->ResetTransform(); +} + +IMPELLER_EXTERN_C +uint32_t ImpellerDisplayListBuilderGetSaveCount( + ImpellerDisplayListBuilder builder) { + return GetPeer(builder)->GetSaveCount(); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderRestoreToCount( + ImpellerDisplayListBuilder builder, + uint32_t count) { + GetPeer(builder)->RestoreToCount(count); +} + +IMPELLER_EXTERN_C +void ImpellerPathRetain(ImpellerPath path) { + ObjectBase::SafeRetain(path); +} + +IMPELLER_EXTERN_C +void ImpellerPathRelease(ImpellerPath path) { + ObjectBase::SafeRelease(path); +} + +IMPELLER_EXTERN_C +ImpellerPathBuilder ImpellerPathBuilderNew() { + return Create().Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderRetain(ImpellerPathBuilder builder) { + ObjectBase::SafeRetain(builder); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderRelease(ImpellerPathBuilder builder) { + ObjectBase::SafeRelease(builder); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderMoveTo(ImpellerPathBuilder builder, + const ImpellerPoint* location) { + GetPeer(builder)->MoveTo(ToImpellerType(*location)); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderLineTo(ImpellerPathBuilder builder, + const ImpellerPoint* location) { + GetPeer(builder)->LineTo(ToImpellerType(*location)); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderQuadraticCurveTo(ImpellerPathBuilder builder, + const ImpellerPoint* control_point, + const ImpellerPoint* end_point) { + GetPeer(builder)->QuadraticCurveTo(ToImpellerType(*control_point), + ToImpellerType(*end_point)); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderCubicCurveTo(ImpellerPathBuilder builder, + const ImpellerPoint* control_point_1, + const ImpellerPoint* control_point_2, + const ImpellerPoint* end_point) { + GetPeer(builder)->CubicCurveTo(ToImpellerType(*control_point_1), // + ToImpellerType(*control_point_2), // + ToImpellerType(*end_point) // + ); +} + +IMPELLER_EXTERN_C void ImpellerPathBuilderAddRect(ImpellerPathBuilder builder, + const ImpellerRect* rect) { + GetPeer(builder)->AddRect(ToImpellerType(*rect)); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderAddArc(ImpellerPathBuilder builder, + const ImpellerRect* oval_bounds, + float start_angle_degrees, + float end_angle_degrees) { + GetPeer(builder)->AddArc(ToImpellerType(*oval_bounds), // + Degrees{start_angle_degrees}, // + Degrees{end_angle_degrees} // + ); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderAddOval(ImpellerPathBuilder builder, + const ImpellerRect* oval_bounds) { + GetPeer(builder)->AddOval(ToImpellerType(*oval_bounds)); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderAddRoundedRect( + ImpellerPathBuilder builder, + const ImpellerRect* rect, + const ImpellerRoundingRadii* rounding_radii) { + GetPeer(builder)->AddRoundedRect(ToImpellerType(*rect), + ToImpellerType(*rounding_radii)); +} + +IMPELLER_EXTERN_C +void ImpellerPathBuilderClose(ImpellerPathBuilder builder) { + GetPeer(builder)->Close(); +} + +IMPELLER_EXTERN_C +ImpellerPath ImpellerPathBuilderCopyPathNew(ImpellerPathBuilder builder, + ImpellerFillType fill) { + return GetPeer(builder)->CopyPath(ToImpellerType(fill)).Leak(); +} + +IMPELLER_EXTERN_C ImpellerPath ImpellerPathBuilderTakePathNew( + ImpellerPathBuilder builder, + ImpellerFillType fill) { + return GetPeer(builder)->TakePath(ToImpellerType(fill)).Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderClipRect(ImpellerDisplayListBuilder builder, + const ImpellerRect* rect, + ImpellerClipOperation op) { + GetPeer(builder)->ClipRect(ToImpellerType(*rect), ToImpellerType(op)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderClipOval(ImpellerDisplayListBuilder builder, + const ImpellerRect* oval_bounds, + ImpellerClipOperation op) { + GetPeer(builder)->ClipOval(ToImpellerType(*oval_bounds), ToImpellerType(op)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderClipRoundedRect( + ImpellerDisplayListBuilder builder, + const ImpellerRect* rect, + const ImpellerRoundingRadii* radii, + ImpellerClipOperation op) { + GetPeer(builder)->ClipRoundedRect(ToImpellerType(*rect), // + ToImpellerType(*radii), // + ToImpellerType(op) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderClipPath(ImpellerDisplayListBuilder builder, + ImpellerPath path, + ImpellerClipOperation op) { + GetPeer(builder)->ClipPath(*GetPeer(path), ToImpellerType(op)); +} + +IMPELLER_EXTERN_C +ImpellerPaint ImpellerPaintNew() { + return Create().Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerPaintRetain(ImpellerPaint paint) { + ObjectBase::SafeRetain(paint); +} + +IMPELLER_EXTERN_C +void ImpellerPaintRelease(ImpellerPaint paint) { + ObjectBase::SafeRelease(paint); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetColor(ImpellerPaint paint, const ImpellerColor* color) { + GetPeer(paint)->SetColor(ToDisplayListType(*color)); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetBlendMode(ImpellerPaint paint, ImpellerBlendMode mode) { + GetPeer(paint)->SetBlendMode(ToImpellerType(mode)); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetDrawStyle(ImpellerPaint paint, ImpellerDrawStyle style) { + GetPeer(paint)->SetDrawStyle(ToDisplayListType(style)); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetStrokeCap(ImpellerPaint paint, ImpellerStrokeCap cap) { + GetPeer(paint)->SetStrokeCap(ToDisplayListType(cap)); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetStrokeJoin(ImpellerPaint paint, ImpellerStrokeJoin join) { + GetPeer(paint)->SetStrokeJoin(ToDisplayListType(join)); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetStrokeWidth(ImpellerPaint paint, float width) { + GetPeer(paint)->SetStrokeWidth(width); +} + +IMPELLER_EXTERN_C +void ImpellerPaintSetStrokeMiter(ImpellerPaint paint, float miter) { + GetPeer(paint)->SetStrokeMiter(miter); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawPaint(ImpellerDisplayListBuilder builder, + ImpellerPaint paint) { + GetPeer(builder)->DrawPaint(*GetPeer(paint)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawLine(ImpellerDisplayListBuilder builder, + const ImpellerPoint* from, + const ImpellerPoint* to, + ImpellerPaint paint) { + GetPeer(builder)->DrawLine(ToImpellerType(*from), // + ToImpellerType(*to), // + *GetPeer(paint) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawDashedLine( + ImpellerDisplayListBuilder builder, + const ImpellerPoint* from, + const ImpellerPoint* to, + float on_length, + float off_length, + ImpellerPaint paint) { + GetPeer(builder)->DrawDashedLine(ToImpellerType(*from), // + ToImpellerType(*to), // + on_length, // + off_length, // + *GetPeer(paint) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawRect(ImpellerDisplayListBuilder builder, + const ImpellerRect* rect, + ImpellerPaint paint) { + GetPeer(builder)->DrawRect(ToImpellerType(*rect), *GetPeer(paint)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawOval(ImpellerDisplayListBuilder builder, + const ImpellerRect* oval_bounds, + ImpellerPaint paint) { + GetPeer(builder)->DrawOval(ToImpellerType(*oval_bounds), *GetPeer(paint)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawRoundedRect( + ImpellerDisplayListBuilder builder, + const ImpellerRect* rect, + const ImpellerRoundingRadii* radii, + ImpellerPaint paint) { + GetPeer(builder)->DrawRoundedRect(ToImpellerType(*rect), // + ToImpellerType(*radii), // + *GetPeer(paint) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawRoundedRectDifference( + ImpellerDisplayListBuilder builder, + const ImpellerRect* outer_rect, + const ImpellerRoundingRadii* outer_radii, + const ImpellerRect* inner_rect, + const ImpellerRoundingRadii* inner_radii, + ImpellerPaint paint) { + GetPeer(builder)->DrawRoundedRectDifference(ToImpellerType(*outer_rect), // + ToImpellerType(*outer_radii), // + ToImpellerType(*inner_rect), // + ToImpellerType(*inner_radii), // + *GetPeer(paint) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawPath(ImpellerDisplayListBuilder builder, + ImpellerPath path, + ImpellerPaint paint) { + GetPeer(builder)->DrawPath(*GetPeer(path), *GetPeer(paint)); +} + +IMPELLER_EXTERN_C +ImpellerTexture ImpellerTextureCreateWithContentsNew( + ImpellerContext context, + const ImpellerTextureDescriptor* descriptor, + const ImpellerMapping* IMPELLER_NONNULL contents, + void* IMPELLER_NULLABLE contents_on_release_user_data) { + TextureDescriptor desc; + desc.storage_mode = StorageMode::kDevicePrivate; + desc.type = TextureType::kTexture2D; + desc.format = ToImpellerType(descriptor->pixel_format); + desc.size = ToImpellerType(descriptor->size); + desc.mip_count = std::min(descriptor->mip_count, 1u); + desc.usage = TextureUsage::kShaderRead; + desc.compression_type = CompressionType::kLossless; + auto texture = Create(*GetPeer(context), desc); + if (!texture->IsValid()) { + VALIDATION_LOG << "Could not create texture."; + return nullptr; + } + // Depending on whether the de-allocation can be delayed, it may be possible + // to avoid a data copy. + if (contents->on_release) { + // Avoids data copy. + auto wrapped_contents = std::make_shared( + contents->data, // data ptr + contents->length, // data length + [contents, contents_on_release_user_data](auto, auto) { + contents->on_release(contents_on_release_user_data); + } // release callback + ); + if (!texture->SetContents(std::move(wrapped_contents))) { + VALIDATION_LOG << "Could not set texture contents."; + return nullptr; + } + } else { + // May copy. + if (!texture->SetContents(contents->data, contents->length)) { + VALIDATION_LOG << "Could not set texture contents."; + return nullptr; + } + } + return texture.Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerTextureRetain(ImpellerTexture texture) { + ObjectBase::SafeRetain(texture); +} + +IMPELLER_EXTERN_C +void ImpellerTextureRelease(ImpellerTexture texture) { + ObjectBase::SafeRelease(texture); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListRetain(ImpellerDisplayList display_list) { + ObjectBase::SafeRetain(display_list); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListRelease(ImpellerDisplayList display_list) { + ObjectBase::SafeRelease(display_list); +} + +IMPELLER_EXTERN_C +ImpellerDisplayList ImpellerDisplayListBuilderCreateDisplayListNew( + ImpellerDisplayListBuilder builder) { + auto dl = GetPeer(builder)->Build(); + if (!dl->IsValid()) { + return nullptr; + } + return dl.Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawDisplayList( + ImpellerDisplayListBuilder builder, + ImpellerDisplayList display_list, + float opacity) { + GetPeer(builder)->DrawDisplayList(*GetPeer(display_list), opacity); +} + +IMPELLER_EXTERN_C +ImpellerSurface ImpellerSurfaceCreateWrappedFBONew(ImpellerContext context, + uint64_t fbo, + ImpellerPixelFormat format, + const ImpellerISize* size) { + return Surface::WrapFBO(*GetPeer(context), // + fbo, // + ToImpellerType(format), // + ToImpellerType(*size)) // + .Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerSurfaceRetain(ImpellerSurface surface) { + ObjectBase::SafeRetain(surface); +} + +IMPELLER_EXTERN_C +void ImpellerSurfaceRelease(ImpellerSurface surface) { + ObjectBase::SafeRelease(surface); +} + +IMPELLER_EXTERN_C +bool ImpellerSurfaceDrawDisplayList(ImpellerSurface surface, + ImpellerDisplayList display_list) { + return GetPeer(surface)->DrawDisplayList(*GetPeer(display_list)); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawTexture(ImpellerDisplayListBuilder builder, + ImpellerTexture texture, + const ImpellerPoint* point, + ImpellerTextureSampling sampling, + ImpellerPaint paint) { + GetPeer(builder)->DrawTexture(*GetPeer(texture), // + ToImpellerType(*point), // + ToDisplayListType(sampling), // + GetPeer(paint) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerDisplayListBuilderDrawTextureRect( + ImpellerDisplayListBuilder builder, + ImpellerTexture texture, + const ImpellerRect* src_rect, + const ImpellerRect* dst_rect, + ImpellerTextureSampling sampling, + ImpellerPaint paint) { + GetPeer(builder)->DrawTextureRect(*GetPeer(texture), // + ToImpellerType(*src_rect), // + ToImpellerType(*dst_rect), // + ToDisplayListType(sampling), // + GetPeer(paint) // + ); +} + +IMPELLER_EXTERN_C +void ImpellerColorSourceRetain(ImpellerColorSource color_source) { + ObjectBase::SafeRetain(color_source); +} + +IMPELLER_EXTERN_C +void ImpellerColorSourceRelease(ImpellerColorSource color_source) { + ObjectBase::SafeRelease(color_source); +} + +static std::pair, std::vector> +ParseColorsAndStops(uint32_t stop_count, + const ImpellerColor* colors, + const float* stops) { + if (stop_count == 0) { + return {}; + } + std::pair, std::vector> result; + result.first.reserve(stop_count); + result.second.reserve(stop_count); + for (size_t i = 0; i < stop_count; i++) { + result.first.emplace_back(ToDisplayListType(colors[i])); + result.second.emplace_back(stops[i]); + } + return result; +} + +IMPELLER_EXTERN_C +ImpellerColorSource ImpellerColorSourceCreateLinearGradientNew( + const ImpellerPoint* start_point, + const ImpellerPoint* end_point, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation) { + const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops); + return ColorSource::MakeLinearGradient( + ToImpellerType(*start_point), // + ToImpellerType(*end_point), // + colors_and_stops.first, // + colors_and_stops.second, // + ToDisplayListType(tile_mode), // + transformation == nullptr ? Matrix{} + : ToImpellerType(*transformation) // + ) + .Leak(); +} + +IMPELLER_EXTERN_C +ImpellerColorSource ImpellerColorSourceCreateRadialGradientNew( + const ImpellerPoint* center, + float radius, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation) { + const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops); + return ColorSource::MakeRadialGradient( + ToImpellerType(*center), // + radius, // + colors_and_stops.first, // + colors_and_stops.second, // + ToDisplayListType(tile_mode), // + transformation == nullptr ? Matrix{} + : ToImpellerType(*transformation) // + ) + .Leak(); +} + +IMPELLER_EXTERN_C +ImpellerColorSource ImpellerColorSourceCreateConicalGradientNew( + const ImpellerPoint* start_center, + float start_radius, + const ImpellerPoint* end_center, + float end_radius, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation) { + const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops); + return ColorSource::MakeConicalGradient( + ToImpellerType(*start_center), // + start_radius, // + ToImpellerType(*end_center), // + end_radius, // + colors_and_stops.first, // + colors_and_stops.second, // + ToDisplayListType(tile_mode), // + transformation == nullptr ? Matrix{} + : ToImpellerType(*transformation) // + ) + .Leak(); +} + +IMPELLER_EXTERN_C +ImpellerColorSource ImpellerColorSourceCreateSweepGradientNew( + const ImpellerPoint* center, + float start, + float end, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation) { + const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops); + return ColorSource::MakeSweepGradient( + ToImpellerType(*center), // + start, // + end, // + colors_and_stops.first, // + colors_and_stops.second, // + ToDisplayListType(tile_mode), // + transformation == nullptr ? Matrix{} + : ToImpellerType(*transformation) // + ) + .Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerColorFilterRetain(ImpellerColorFilter color_filter) { + ObjectBase::SafeRetain(color_filter); +} + +IMPELLER_EXTERN_C +void ImpellerColorFilterRelease(ImpellerColorFilter color_filter) { + ObjectBase::SafeRelease(color_filter); +} + +IMPELLER_EXTERN_C +ImpellerColorFilter ImpellerColorFilterCreateBlendNew( + const ImpellerColor* color, + ImpellerBlendMode blend_mode) { + return ColorFilter::MakeBlend(ToImpellerType(*color), + ToImpellerType(blend_mode)) + .Leak(); +} + +IMPELLER_EXTERN_C +ImpellerColorFilter ImpellerColorFilterCreateColorMatrixNew( + const ImpellerColorMatrix* color_matrix) { + return ColorFilter::MakeMatrix(color_matrix->m).Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerMaskFilterRetain(ImpellerMaskFilter mask_filter) { + ObjectBase::SafeRetain(mask_filter); +} + +IMPELLER_EXTERN_C +void ImpellerMaskFilterRelease(ImpellerMaskFilter mask_filter) { + ObjectBase::SafeRelease(mask_filter); +} + +IMPELLER_EXTERN_C +ImpellerMaskFilter ImpellerMaskFilterCreateBlurNew(ImpellerBlurStyle style, + float sigma) { + return MaskFilter::MakeBlur(ToDisplayListType(style), sigma).Leak(); +} + +IMPELLER_EXTERN_C +void ImpellerImageFilterRetain(ImpellerImageFilter image_filter) { + ObjectBase::SafeRetain(image_filter); +} + +IMPELLER_EXTERN_C +void ImpellerImageFilterRelease(ImpellerImageFilter image_filter) { + ObjectBase::SafeRelease(image_filter); +} + +IMPELLER_EXTERN_C +ImpellerImageFilter ImpellerImageFilterCreateBlurNew( + float x_sigma, + float y_sigma, + ImpellerTileMode tile_mode) { + return ImageFilter::MakeBlur(x_sigma, y_sigma, ToDisplayListType(tile_mode)) + .Leak(); +} + +IMPELLER_EXTERN_C +ImpellerImageFilter ImpellerImageFilterCreateDilateNew(float x_radius, + float y_radius) { + return ImageFilter::MakeDilate(x_radius, y_radius).Leak(); +} + +IMPELLER_EXTERN_C +ImpellerImageFilter ImpellerImageFilterCreateErodeNew(float x_radius, + float y_radius) { + return ImageFilter::MakeErode(x_radius, y_radius).Leak(); +} + +IMPELLER_EXTERN_C +ImpellerImageFilter ImpellerImageFilterCreateMatrixNew( + const ImpellerMatrix* matrix, + ImpellerTextureSampling sampling) { + return ImageFilter::MakeMatrix(ToImpellerType(*matrix), + ToDisplayListType(sampling)) + .Leak(); +} + +IMPELLER_EXTERN_C +ImpellerImageFilter ImpellerImageFilterCreateComposeNew( + ImpellerImageFilter outer, + ImpellerImageFilter inner) { + return ImageFilter::MakeCompose(*GetPeer(outer), *GetPeer(inner)).Leak(); +} + +void ImpellerPaintSetColorFilter(ImpellerPaint paint, + ImpellerColorFilter color_filter) { + GetPeer(paint)->SetColorFilter(*GetPeer(color_filter)); +} + +void ImpellerPaintSetColorSource(ImpellerPaint paint, + ImpellerColorSource color_source) { + GetPeer(paint)->SetColorSource(*GetPeer(color_source)); +} + +void ImpellerPaintSetImageFilter(ImpellerPaint paint, + ImpellerImageFilter image_filter) { + GetPeer(paint)->SetImageFilter(*GetPeer(image_filter)); +} + +void ImpellerPaintSetMaskFilter(ImpellerPaint paint, + ImpellerMaskFilter mask_filter) { + GetPeer(paint)->SetMaskFilter(*GetPeer(mask_filter)); +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/impeller.h b/engine/src/flutter/impeller/toolkit/interop/impeller.h new file mode 100644 index 00000000000..62ebd6fbb2d --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/impeller.h @@ -0,0 +1,773 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_IMPELLER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMPELLER_H_ + +#include +#include +#include + +#if defined(__cplusplus) +#define IMPELLER_EXTERN_C extern "C" +#define IMPELLER_EXTERN_C_BEGIN IMPELLER_EXTERN_C { +#define IMPELLER_EXTERN_C_END } +#else // defined(__cplusplus) +#define IMPELLER_EXTERN_C +#define IMPELLER_EXTERN_C_BEGIN +#define IMPELLER_EXTERN_C_END +#endif // defined(__cplusplus) + +#ifndef IMPELLER_EXPORT +#define IMPELLER_EXPORT +#endif // IMPELLER_EXPORT + +#ifdef __clang__ +#define IMPELLER_NULLABLE _Nullable +#define IMPELLER_NONNULL _Nonnull +#else // __clang__ +#define IMPELLER_NULLABLE +#define IMPELLER_NONNULL +#endif // __clang__ + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202000L) +#define IMPELLER_NODISCARD [[nodiscard]] +#else // defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202000L) +#define IMPELLER_NODISCARD +#endif // defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202000L) + +IMPELLER_EXTERN_C_BEGIN + +//------------------------------------------------------------------------------ +// Versioning +//------------------------------------------------------------------------------ + +#define IMPELLER_MAKE_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | \ + (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + +#define IMPELLER_VERSION_VARIANT 1 +#define IMPELLER_VERSION_MAJOR 1 +#define IMPELLER_VERSION_MINOR 0 +#define IMPELLER_VERSION_PATCH 0 + +#define IMPELLER_VERSION \ + IMPELLER_MAKE_VERSION(IMPELLER_VERSION_VARIANT, IMPELLER_VERSION_MAJOR, \ + IMPELLER_VERSION_MINOR, IMPELLER_VERSION_PATCH) + +#define IMPELLER_VERSION_GET_VARIANT(version) ((uint32_t)(version) >> 29U) +#define IMPELLER_VERSION_GET_MAJOR(version) \ + (((uint32_t)(version) >> 22U) & 0x7FU) +#define IMPELLER_VERSION_GET_MINOR(version) \ + (((uint32_t)(version) >> 12U) & 0x3FFU) +#define IMPELLER_VERSION_GET_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +//------------------------------------------------------------------------------ +// Handles +//------------------------------------------------------------------------------ + +#define IMPELLER_INTERNAL_HANDLE_NAME(handle) handle##_ +#define IMPELLER_DEFINE_HANDLE(handle) \ + typedef struct IMPELLER_INTERNAL_HANDLE_NAME(handle) * handle; + +IMPELLER_DEFINE_HANDLE(ImpellerColorFilter); +IMPELLER_DEFINE_HANDLE(ImpellerColorSource); +IMPELLER_DEFINE_HANDLE(ImpellerContext); +IMPELLER_DEFINE_HANDLE(ImpellerDisplayList); +IMPELLER_DEFINE_HANDLE(ImpellerDisplayListBuilder); +IMPELLER_DEFINE_HANDLE(ImpellerImageFilter); +IMPELLER_DEFINE_HANDLE(ImpellerMaskFilter); +IMPELLER_DEFINE_HANDLE(ImpellerPaint); +IMPELLER_DEFINE_HANDLE(ImpellerPath); +IMPELLER_DEFINE_HANDLE(ImpellerPathBuilder); +IMPELLER_DEFINE_HANDLE(ImpellerSurface); +IMPELLER_DEFINE_HANDLE(ImpellerTexture); + +//------------------------------------------------------------------------------ +// Signatures +//------------------------------------------------------------------------------ + +typedef void (*ImpellerCallback)(void* IMPELLER_NULLABLE user_data); +typedef void* IMPELLER_NULLABLE (*ImpellerProcAddressCallback)( + const char* IMPELLER_NONNULL proc_name, + void* IMPELLER_NULLABLE user_data); + +//------------------------------------------------------------------------------ +// Enumerations +//------------------------------------------------------------------------------ +typedef enum ImpellerFillType { + kImpellerFillTypeNonZero, + kImpellerFillTypeOdd, +} ImpellerFillType; + +typedef enum ImpellerClipOperation { + kImpellerClipOperationDifference, + kImpellerClipOperationIntersect, +} ImpellerClipOperation; + +typedef enum ImpellerBlendMode { + kImpellerBlendModeClear, + kImpellerBlendModeSource, + kImpellerBlendModeDestination, + kImpellerBlendModeSourceOver, + kImpellerBlendModeDestinationOver, + kImpellerBlendModeSourceIn, + kImpellerBlendModeDestinationIn, + kImpellerBlendModeSourceOut, + kImpellerBlendModeDestinationOut, + kImpellerBlendModeSourceATop, + kImpellerBlendModeDestinationATop, + kImpellerBlendModeXor, + kImpellerBlendModePlus, + kImpellerBlendModeModulate, + kImpellerBlendModeScreen, + kImpellerBlendModeOverlay, + kImpellerBlendModeDarken, + kImpellerBlendModeLighten, + kImpellerBlendModeColorDodge, + kImpellerBlendModeColorBurn, + kImpellerBlendModeHardLight, + kImpellerBlendModeSoftLight, + kImpellerBlendModeDifference, + kImpellerBlendModeExclusion, + kImpellerBlendModeMultiply, + kImpellerBlendModeHue, + kImpellerBlendModeSaturation, + kImpellerBlendModeColor, + kImpellerBlendModeLuminosity, +} ImpellerBlendMode; + +typedef enum ImpellerDrawStyle { + kImpellerDrawStyleFill, + kImpellerDrawStyleStroke, + kImpellerDrawStyleStrokeAndFill, +} ImpellerDrawStyle; + +typedef enum ImpellerStrokeCap { + kImpellerStrokeCapButt, + kImpellerStrokeCapRound, + kImpellerStrokeCapSquare, +} ImpellerStrokeCap; + +typedef enum ImpellerStrokeJoin { + kImpellerStrokeJoinMiter, + kImpellerStrokeJoinRound, + kImpellerStrokeJoinBevel, +} ImpellerStrokeJoin; + +typedef enum ImpellerPixelFormat { + kImpellerPixelFormatRGBA8888, +} ImpellerPixelFormat; + +typedef enum ImpellerTextureSampling { + kImpellerTextureSamplingNearestNeighbor, + kImpellerTextureSamplingLinear, +} ImpellerTextureSampling; + +typedef enum ImpellerTileMode { + kImpellerTileModeClamp, + kImpellerTileModeRepeat, + kImpellerTileModeMirror, + kImpellerTileModeDecal, +} ImpellerTileMode; + +typedef enum ImpellerBlurStyle { + kImpellerBlurStyleNormal, + kImpellerBlurStyleSolid, + kImpellerBlurStyleOuter, + kImpellerBlurStyleInner, +} ImpellerBlurStyle; + +typedef enum ImpellerColorSpace { + kImpellerColorSpaceSRGB, + kImpellerColorSpaceExtendedSRGB, + kImpellerColorSpaceDisplayP3, +} ImpellerColorSpace; + +//------------------------------------------------------------------------------ +// Non-opaque structs +//------------------------------------------------------------------------------ +typedef struct ImpellerRect { + float x; + float y; + float width; + float height; +} ImpellerRect; + +typedef struct ImpellerPoint { + float x; + float y; +} ImpellerPoint; + +typedef struct ImpellerSize { + float width; + float height; +} ImpellerSize; + +typedef struct ImpellerISize { + int64_t width; + int64_t height; +} ImpellerISize; + +typedef struct ImpellerMatrix { + float m[16]; +} ImpellerMatrix; + +typedef struct ImpellerColorMatrix { + float m[20]; +} ImpellerColorMatrix; + +typedef struct ImpellerRoundingRadii { + ImpellerPoint top_left; + ImpellerPoint bottom_left; + ImpellerPoint top_right; + ImpellerPoint bottom_right; +} ImpellerRoundingRadii; + +typedef struct ImpellerColor { + float red; + float green; + float blue; + float alpha; + ImpellerColorSpace color_space; +} ImpellerColor; + +typedef struct ImpellerTextureDescriptor { + ImpellerPixelFormat pixel_format; + ImpellerISize size; + uint32_t mip_count; +} ImpellerTextureDescriptor; + +typedef struct ImpellerMapping { + const uint8_t* IMPELLER_NONNULL data; + uint64_t length; + ImpellerCallback IMPELLER_NULLABLE on_release; +} ImpellerMapping; + +//------------------------------------------------------------------------------ +// Version +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +uint32_t ImpellerGetVersion(); + +//------------------------------------------------------------------------------ +// Context +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerContext IMPELLER_NULLABLE +ImpellerContextCreateOpenGLESNew( + uint32_t version, + ImpellerProcAddressCallback IMPELLER_NONNULL gl_proc_address_callback, + void* IMPELLER_NULLABLE gl_proc_address_callback_user_data); + +IMPELLER_EXPORT +void ImpellerContextRetain(ImpellerContext IMPELLER_NULLABLE context); + +IMPELLER_EXPORT +void ImpellerContextRelease(ImpellerContext IMPELLER_NULLABLE context); + +//------------------------------------------------------------------------------ +// Surface +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerSurface IMPELLER_NULLABLE +ImpellerSurfaceCreateWrappedFBONew(ImpellerContext IMPELLER_NULLABLE context, + uint64_t fbo, + ImpellerPixelFormat format, + const ImpellerISize* IMPELLER_NULLABLE size); + +IMPELLER_EXPORT +void ImpellerSurfaceRetain(ImpellerSurface IMPELLER_NULLABLE surface); + +IMPELLER_EXPORT +void ImpellerSurfaceRelease(ImpellerSurface IMPELLER_NULLABLE surface); + +IMPELLER_EXPORT +bool ImpellerSurfaceDrawDisplayList( + ImpellerSurface IMPELLER_NULLABLE surface, + ImpellerDisplayList IMPELLER_NONNULL display_list); + +//------------------------------------------------------------------------------ +// Path +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerPathRetain(ImpellerPath IMPELLER_NULLABLE path); + +IMPELLER_EXPORT +void ImpellerPathRelease(ImpellerPath IMPELLER_NULLABLE path); + +//------------------------------------------------------------------------------ +// Path Builder +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerPathBuilder IMPELLER_NULLABLE +ImpellerPathBuilderNew(); + +IMPELLER_EXPORT +void ImpellerPathBuilderRetain(ImpellerPathBuilder IMPELLER_NULLABLE builder); + +IMPELLER_EXPORT +void ImpellerPathBuilderRelease(ImpellerPathBuilder IMPELLER_NULLABLE builder); + +IMPELLER_EXPORT +void ImpellerPathBuilderMoveTo(ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerPoint* IMPELLER_NONNULL location); + +IMPELLER_EXPORT +void ImpellerPathBuilderLineTo(ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerPoint* IMPELLER_NONNULL location); + +IMPELLER_EXPORT +void ImpellerPathBuilderQuadraticCurveTo( + ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerPoint* IMPELLER_NONNULL control_point, + const ImpellerPoint* IMPELLER_NONNULL end_point); + +IMPELLER_EXPORT +void ImpellerPathBuilderCubicCurveTo( + ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerPoint* IMPELLER_NONNULL control_point_1, + const ImpellerPoint* IMPELLER_NONNULL control_point_2, + const ImpellerPoint* IMPELLER_NONNULL end_point); + +IMPELLER_EXPORT +void ImpellerPathBuilderAddRect(ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL rect); + +IMPELLER_EXPORT +void ImpellerPathBuilderAddArc(ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL oval_bounds, + float start_angle_degrees, + float end_angle_degrees); + +IMPELLER_EXPORT +void ImpellerPathBuilderAddOval( + ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL oval_bounds); + +IMPELLER_EXPORT +void ImpellerPathBuilderAddRoundedRect( + ImpellerPathBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL rect, + const ImpellerRoundingRadii* IMPELLER_NONNULL rounding_radii); + +IMPELLER_EXPORT +void ImpellerPathBuilderClose(ImpellerPathBuilder IMPELLER_NONNULL builder); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerPath IMPELLER_NULLABLE +ImpellerPathBuilderCopyPathNew(ImpellerPathBuilder IMPELLER_NONNULL builder, + ImpellerFillType fill); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerPath IMPELLER_NULLABLE +ImpellerPathBuilderTakePathNew(ImpellerPathBuilder IMPELLER_NONNULL builder, + ImpellerFillType fill); + +//------------------------------------------------------------------------------ +// Paint +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerPaint IMPELLER_NULLABLE +ImpellerPaintNew(); + +IMPELLER_EXPORT +void ImpellerPaintRetain(ImpellerPaint IMPELLER_NULLABLE paint); + +IMPELLER_EXPORT +void ImpellerPaintRelease(ImpellerPaint IMPELLER_NULLABLE paint); + +IMPELLER_EXPORT +void ImpellerPaintSetColor(ImpellerPaint IMPELLER_NONNULL paint, + const ImpellerColor* IMPELLER_NONNULL color); + +IMPELLER_EXPORT +void ImpellerPaintSetBlendMode(ImpellerPaint IMPELLER_NONNULL paint, + ImpellerBlendMode mode); + +IMPELLER_EXPORT +void ImpellerPaintSetDrawStyle(ImpellerPaint IMPELLER_NONNULL paint, + ImpellerDrawStyle style); + +IMPELLER_EXPORT +void ImpellerPaintSetStrokeCap(ImpellerPaint IMPELLER_NONNULL paint, + ImpellerStrokeCap cap); + +IMPELLER_EXPORT +void ImpellerPaintSetStrokeJoin(ImpellerPaint IMPELLER_NONNULL paint, + ImpellerStrokeJoin join); + +IMPELLER_EXPORT +void ImpellerPaintSetStrokeWidth(ImpellerPaint IMPELLER_NONNULL paint, + float width); + +IMPELLER_EXPORT +void ImpellerPaintSetStrokeMiter(ImpellerPaint IMPELLER_NONNULL paint, + float miter); + +IMPELLER_EXPORT +void ImpellerPaintSetColorFilter( + ImpellerPaint IMPELLER_NONNULL paint, + ImpellerColorFilter IMPELLER_NONNULL color_filter); + +IMPELLER_EXPORT +void ImpellerPaintSetColorSource( + ImpellerPaint IMPELLER_NONNULL paint, + ImpellerColorSource IMPELLER_NONNULL color_source); + +IMPELLER_EXPORT +void ImpellerPaintSetImageFilter( + ImpellerPaint IMPELLER_NONNULL paint, + ImpellerImageFilter IMPELLER_NONNULL image_filter); + +IMPELLER_EXPORT +void ImpellerPaintSetMaskFilter( + ImpellerPaint IMPELLER_NONNULL paint, + ImpellerMaskFilter IMPELLER_NONNULL mask_filter); + +//------------------------------------------------------------------------------ +// Texture +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerTexture IMPELLER_NULLABLE +ImpellerTextureCreateWithContentsNew( + ImpellerContext IMPELLER_NONNULL context, + const ImpellerTextureDescriptor* IMPELLER_NONNULL descriptor, + const ImpellerMapping* IMPELLER_NONNULL contents, + void* IMPELLER_NULLABLE contents_on_release_user_data); + +IMPELLER_EXPORT +void ImpellerTextureRetain(ImpellerTexture IMPELLER_NULLABLE texture); + +IMPELLER_EXPORT +void ImpellerTextureRelease(ImpellerTexture IMPELLER_NULLABLE texture); + +//------------------------------------------------------------------------------ +// Color Sources +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerColorSourceRetain( + ImpellerColorSource IMPELLER_NULLABLE color_source); + +IMPELLER_EXPORT +void ImpellerColorSourceRelease( + ImpellerColorSource IMPELLER_NULLABLE color_source); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerColorSource IMPELLER_NULLABLE +ImpellerColorSourceCreateLinearGradientNew( + const ImpellerPoint* IMPELLER_NONNULL start_point, + const ImpellerPoint* IMPELLER_NONNULL end_point, + uint32_t stop_count, + const ImpellerColor* IMPELLER_NONNULL colors, + const float* IMPELLER_NONNULL stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* IMPELLER_NULLABLE transformation); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerColorSource IMPELLER_NULLABLE +ImpellerColorSourceCreateRadialGradientNew( + const ImpellerPoint* IMPELLER_NONNULL center, + float radius, + uint32_t stop_count, + const ImpellerColor* IMPELLER_NONNULL colors, + const float* IMPELLER_NONNULL stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* IMPELLER_NULLABLE transformation); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerColorSource IMPELLER_NULLABLE +ImpellerColorSourceCreateConicalGradientNew( + const ImpellerPoint* IMPELLER_NONNULL start_center, + float start_radius, + const ImpellerPoint* IMPELLER_NONNULL end_center, + float end_radius, + uint32_t stop_count, + const ImpellerColor* IMPELLER_NONNULL colors, + const float* IMPELLER_NONNULL stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* IMPELLER_NULLABLE transformation); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerColorSource IMPELLER_NULLABLE +ImpellerColorSourceCreateSweepGradientNew( + const ImpellerPoint* IMPELLER_NONNULL center, + float start, + float end, + uint32_t stop_count, + const ImpellerColor* IMPELLER_NONNULL colors, + const float* IMPELLER_NONNULL stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* IMPELLER_NULLABLE transformation); + +//------------------------------------------------------------------------------ +// Color Filters +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerColorFilterRetain( + ImpellerColorFilter IMPELLER_NULLABLE color_filter); + +IMPELLER_EXPORT +void ImpellerColorFilterRelease( + ImpellerColorFilter IMPELLER_NULLABLE color_filter); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerColorFilter IMPELLER_NULLABLE +ImpellerColorFilterCreateBlendNew(const ImpellerColor* IMPELLER_NONNULL color, + ImpellerBlendMode blend_mode); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerColorFilter IMPELLER_NULLABLE +ImpellerColorFilterCreateColorMatrixNew( + const ImpellerColorMatrix* IMPELLER_NONNULL color_matrix); + +//------------------------------------------------------------------------------ +// Mask Filters +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerMaskFilterRetain(ImpellerMaskFilter IMPELLER_NULLABLE mask_filter); + +IMPELLER_EXPORT +void ImpellerMaskFilterRelease( + ImpellerMaskFilter IMPELLER_NULLABLE mask_filter); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerMaskFilter IMPELLER_NULLABLE +ImpellerMaskFilterCreateBlurNew(ImpellerBlurStyle style, float sigma); + +//------------------------------------------------------------------------------ +// Image Filters +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerImageFilterRetain( + ImpellerImageFilter IMPELLER_NULLABLE image_filter); + +IMPELLER_EXPORT +void ImpellerImageFilterRelease( + ImpellerImageFilter IMPELLER_NULLABLE image_filter); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerImageFilter IMPELLER_NULLABLE +ImpellerImageFilterCreateBlurNew(float x_sigma, + float y_sigma, + ImpellerTileMode tile_mode); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerImageFilter IMPELLER_NULLABLE +ImpellerImageFilterCreateDilateNew(float x_radius, float y_radius); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerImageFilter IMPELLER_NULLABLE +ImpellerImageFilterCreateErodeNew(float x_radius, float y_radius); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerImageFilter IMPELLER_NULLABLE +ImpellerImageFilterCreateMatrixNew( + const ImpellerMatrix* IMPELLER_NONNULL matrix, + ImpellerTextureSampling sampling); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerImageFilter IMPELLER_NULLABLE +ImpellerImageFilterCreateComposeNew(ImpellerImageFilter IMPELLER_NONNULL outer, + ImpellerImageFilter IMPELLER_NONNULL inner); + +//------------------------------------------------------------------------------ +// Display List +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerDisplayListRetain( + ImpellerDisplayList IMPELLER_NULLABLE display_list); + +IMPELLER_EXPORT +void ImpellerDisplayListRelease( + ImpellerDisplayList IMPELLER_NULLABLE display_list); + +//------------------------------------------------------------------------------ +// Display List Builder +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerDisplayListBuilder IMPELLER_NULLABLE +ImpellerDisplayListBuilderNew(const ImpellerRect* IMPELLER_NULLABLE cull_rect); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderRetain( + ImpellerDisplayListBuilder IMPELLER_NULLABLE builder); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderRelease( + ImpellerDisplayListBuilder IMPELLER_NULLABLE builder); + +IMPELLER_EXPORT IMPELLER_NODISCARD ImpellerDisplayList IMPELLER_NULLABLE +ImpellerDisplayListBuilderCreateDisplayListNew( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder); + +//------------------------------------------------------------------------------ +// Display List Builder: Managing the transformation stack. +//------------------------------------------------------------------------------ +IMPELLER_EXPORT +void ImpellerDisplayListBuilderSave( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderSaveLayer( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL bounds, + ImpellerPaint IMPELLER_NULLABLE paint, + ImpellerImageFilter IMPELLER_NULLABLE backdrop); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderRestore( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderScale( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + float x_scale, + float y_scale); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderRotate( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + float angle_degrees); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderTranslate( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + float x_translation, + float y_translation); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderSetTransform( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerMatrix* IMPELLER_NONNULL transform); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderGetTransform( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerMatrix* IMPELLER_NONNULL out_transform); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderResetTransform( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder); + +IMPELLER_EXPORT +uint32_t ImpellerDisplayListBuilderGetSaveCount( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderRestoreToCount( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + uint32_t count); + +//------------------------------------------------------------------------------ +// Display List Builder: Clipping +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderClipRect( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL rect, + ImpellerClipOperation op); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderClipOval( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL oval_bounds, + ImpellerClipOperation op); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderClipRoundedRect( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL rect, + const ImpellerRoundingRadii* IMPELLER_NONNULL radii, + ImpellerClipOperation op); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderClipPath( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerPath IMPELLER_NONNULL path, + ImpellerClipOperation op); + +//------------------------------------------------------------------------------ +// Display List Builder: Drawing Shapes +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawPaint( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawLine( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerPoint* IMPELLER_NONNULL from, + const ImpellerPoint* IMPELLER_NONNULL to, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawDashedLine( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerPoint* IMPELLER_NONNULL from, + const ImpellerPoint* IMPELLER_NONNULL to, + float on_length, + float off_length, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawRect( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL rect, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawOval( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL oval_bounds, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawRoundedRect( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL rect, + const ImpellerRoundingRadii* IMPELLER_NONNULL radii, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawRoundedRectDifference( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + const ImpellerRect* IMPELLER_NONNULL outer_rect, + const ImpellerRoundingRadii* IMPELLER_NONNULL outer_radii, + const ImpellerRect* IMPELLER_NONNULL inner_rect, + const ImpellerRoundingRadii* IMPELLER_NONNULL inner_radii, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawPath( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerPath IMPELLER_NONNULL path, + ImpellerPaint IMPELLER_NONNULL paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawDisplayList( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerDisplayList IMPELLER_NONNULL display_list, + float opacity); + +//------------------------------------------------------------------------------ +// Display List Builder: Drawing Textures +//------------------------------------------------------------------------------ + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawTexture( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerTexture IMPELLER_NONNULL texture, + const ImpellerPoint* IMPELLER_NONNULL point, + ImpellerTextureSampling sampling, + ImpellerPaint IMPELLER_NULLABLE paint); + +IMPELLER_EXPORT +void ImpellerDisplayListBuilderDrawTextureRect( + ImpellerDisplayListBuilder IMPELLER_NONNULL builder, + ImpellerTexture IMPELLER_NONNULL texture, + const ImpellerRect* IMPELLER_NONNULL src_rect, + const ImpellerRect* IMPELLER_NONNULL dst_rect, + ImpellerTextureSampling sampling, + ImpellerPaint IMPELLER_NULLABLE paint); + +IMPELLER_EXTERN_C_END + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMPELLER_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/impeller_c.c b/engine/src/flutter/impeller/toolkit/interop/impeller_c.c new file mode 100644 index 00000000000..721e5d8c3a5 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/impeller_c.c @@ -0,0 +1,9 @@ +// 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 "impeller.h" + +// This C file is only present to make sure the C header can be imported cleanly +// in a C translation unit. Accidental additions of C++ constructs to the header +// will lead to compilation errors in this translation unit. diff --git a/engine/src/flutter/impeller/toolkit/interop/impeller_unittests.cc b/engine/src/flutter/impeller/toolkit/interop/impeller_unittests.cc new file mode 100644 index 00000000000..03ef5577241 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/impeller_unittests.cc @@ -0,0 +1,110 @@ +// 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/testing/testing.h" +#include "impeller/toolkit/interop/context.h" +#include "impeller/toolkit/interop/dl.h" +#include "impeller/toolkit/interop/dl_builder.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/paint.h" +#include "impeller/toolkit/interop/playground_test.h" +#include "impeller/toolkit/interop/surface.h" +#include "impeller/toolkit/interop/texture.h" + +namespace impeller::interop::testing { + +using InteropPlaygroundTest = PlaygroundTest; +INSTANTIATE_OPENGLES_PLAYGROUND_SUITE(InteropPlaygroundTest); + +TEST_P(InteropPlaygroundTest, CanCreateContext) { + auto context = CreateContext(); + ASSERT_TRUE(context); +} + +TEST_P(InteropPlaygroundTest, CanCreateDisplayListBuilder) { + auto builder = ImpellerDisplayListBuilderNew(nullptr); + ASSERT_NE(builder, nullptr); + ImpellerMatrix matrix; + ImpellerDisplayListBuilderGetTransform(builder, &matrix); + ASSERT_TRUE(ToImpellerType(matrix).IsIdentity()); + ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 1u); + ImpellerDisplayListBuilderSave(builder); + ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 2u); + // ImpellerDisplayListBuilderSave(nullptr); <-- Compiler error. + ImpellerDisplayListBuilderRestore(builder); + ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 1u); + ImpellerDisplayListBuilderRelease(builder); +} + +TEST_P(InteropPlaygroundTest, CanCreateSurface) { + auto context = CreateContext(); + ASSERT_TRUE(context); + const auto window_size = GetWindowSize(); + ImpellerISize size = {window_size.width, window_size.height}; + auto surface = Adopt(ImpellerSurfaceCreateWrappedFBONew( + context.GetC(), // + 0u, // + ImpellerPixelFormat::kImpellerPixelFormatRGBA8888, // + &size) // + ); + ASSERT_TRUE(surface); +} + +TEST_P(InteropPlaygroundTest, CanDrawRect) { + auto builder = + Adopt(ImpellerDisplayListBuilderNew(nullptr)); + auto paint = Adopt(ImpellerPaintNew()); + ImpellerColor color = {0.0, 0.0, 1.0, 1.0}; + ImpellerPaintSetColor(paint.GetC(), &color); + ImpellerRect rect = {10, 20, 100, 200}; + ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC()); + color = {1.0, 0.0, 0.0, 1.0}; + ImpellerPaintSetColor(paint.GetC(), &color); + ImpellerDisplayListBuilderTranslate(builder.GetC(), 110, 210); + ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC()); + auto dl = Adopt( + ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC())); + ASSERT_TRUE(dl); + ASSERT_TRUE( + OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool { + ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC()); + return true; + })); +} + +TEST_P(InteropPlaygroundTest, CanDrawImage) { + auto compressed = LoadFixtureImageCompressed( + flutter::testing::OpenFixtureAsMapping("boston.jpg")); + ASSERT_NE(compressed, nullptr); + auto decompressed = compressed->Decode().ConvertToRGBA(); + ASSERT_TRUE(decompressed.IsValid()); + ImpellerMapping mapping = {}; + mapping.data = decompressed.GetAllocation()->GetMapping(); + mapping.length = decompressed.GetAllocation()->GetSize(); + + auto context = GetInteropContext(); + ImpellerTextureDescriptor desc = {}; + desc.pixel_format = ImpellerPixelFormat::kImpellerPixelFormatRGBA8888; + desc.size = {decompressed.GetSize().width, decompressed.GetSize().height}; + desc.mip_count = 1u; + auto texture = Adopt(ImpellerTextureCreateWithContentsNew( + context.GetC(), &desc, &mapping, nullptr)); + ASSERT_TRUE(texture); + auto builder = + Adopt(ImpellerDisplayListBuilderNew(nullptr)); + ImpellerPoint point = {100, 100}; + ImpellerDisplayListBuilderDrawTexture(builder.GetC(), texture.GetC(), &point, + kImpellerTextureSamplingLinear, + nullptr); + auto dl = Adopt( + ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC())); + ASSERT_TRUE( + OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool { + ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC()); + return true; + })); +} + +} // namespace impeller::interop::testing diff --git a/engine/src/flutter/impeller/toolkit/interop/mask_filter.cc b/engine/src/flutter/impeller/toolkit/interop/mask_filter.cc new file mode 100644 index 00000000000..3ff80b82a18 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/mask_filter.cc @@ -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. + +#include "impeller/toolkit/interop/mask_filter.h" + +namespace impeller::interop { + +ScopedObject MaskFilter::MakeBlur(flutter::DlBlurStyle style, + float sigma) { + auto filter = flutter::DlBlurMaskFilter::Make(style, sigma); + if (!filter) { + return nullptr; + } + return Create(std::move(filter)); +} + +MaskFilter::MaskFilter(std::shared_ptr mask_filter) + : mask_filter_(std::move(mask_filter)) {} + +MaskFilter::~MaskFilter() = default; + +const std::shared_ptr& MaskFilter::GetMaskFilter() + const { + return mask_filter_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/mask_filter.h b/engine/src/flutter/impeller/toolkit/interop/mask_filter.h new file mode 100644 index 00000000000..0d83e017b50 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/mask_filter.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_IMPELLER_TOOLKIT_INTEROP_MASK_FILTER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_MASK_FILTER_H_ + +#include "flutter/display_list/effects/dl_mask_filter.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class MaskFilter final + : public Object { + public: + static ScopedObject MakeBlur(flutter::DlBlurStyle style, + float sigma); + + explicit MaskFilter(std::shared_ptr mask_filter); + + ~MaskFilter() override; + + MaskFilter(const MaskFilter&) = delete; + + MaskFilter& operator=(const MaskFilter&) = delete; + + const std::shared_ptr& GetMaskFilter() const; + + public: + std::shared_ptr mask_filter_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_MASK_FILTER_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/object.cc b/engine/src/flutter/impeller/toolkit/interop/object.cc new file mode 100644 index 00000000000..7b21ca6132b --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/object.cc @@ -0,0 +1,11 @@ +// 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 "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +// + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/object.h b/engine/src/flutter/impeller/toolkit/interop/object.h new file mode 100644 index 00000000000..cc97eb72fbe --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/object.h @@ -0,0 +1,167 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_OBJECT_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_OBJECT_H_ + +#include +#include + +#include "flutter/fml/logging.h" + +namespace impeller::interop { + +class ObjectBase { + public: + ObjectBase() = default; + + virtual ~ObjectBase() = default; + + ObjectBase(const ObjectBase&) = delete; + + ObjectBase(ObjectBase&&) = delete; + + ObjectBase& operator=(const ObjectBase&) = delete; + + ObjectBase& operator=(ObjectBase&&) = delete; + + void Retain() { ref_count_++; } + + void Release() { + if (ref_count_-- == 1u) { + delete this; + } + } + + static void SafeRetain(void* ptr) { + if (ptr) { + reinterpret_cast(ptr)->Retain(); + } + } + + static void SafeRelease(void* ptr) { + if (ptr) { + reinterpret_cast(ptr)->Release(); + } + } + + uint64_t GetRefCountForTests() const { return ref_count_; } + + private: + std::atomic_uint64_t ref_count_ = {1u}; +}; + +template +class Object : public ObjectBase { + public: + using InteropClass = Clasz; + using InteropCSibling = CSibling; +}; + +enum class AdoptTag { + kAdopted, +}; + +template +class ScopedObject final { + public: + ScopedObject() = default; + + ScopedObject(std::nullptr_t) // NOLINT(google-explicit-constructor) + {} + + explicit ScopedObject(Object* ptr, AdoptTag) : object_(ptr) {} + + explicit ScopedObject(Object* ptr) : object_(ptr) { + if (object_) { + object_->Retain(); + } + } + + ~ScopedObject() { Release(); } + + ScopedObject(const ScopedObject& other) : ScopedObject(other.Get()) {} + + ScopedObject(ScopedObject&& other) { std::swap(object_, other.object_); } + + ScopedObject& operator=(const ScopedObject& other) { + // Self assignment. + if (object_ == other.object_) { + return *this; + } + if (other.object_) { + other.object_->Retain(); + } + Release(); + FML_DCHECK(object_ == nullptr); + object_ = other.object_; + return *this; + } + + ScopedObject& operator=(ScopedObject&& other) { + std::swap(object_, other.object_); + return *this; + } + + Object* Get() const { return object_; } + + typename Object::InteropCSibling* GetC() const { + return reinterpret_cast(Get()); + } + + Object& operator*() const { + FML_DCHECK(object_); + return *object_; + } + + Object* operator->() const { + FML_DCHECK(object_); + return object_; + } + + explicit operator bool() const { return !!object_; } + + [[nodiscard]] + typename Object::InteropCSibling* Leak() { + auto to_leak = object_; + object_ = nullptr; + return reinterpret_cast(to_leak); + } + + private: + Object* object_ = nullptr; + + void Release() { + if (object_) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDelete) + object_->Release(); + object_ = nullptr; + } + } +}; + +template +ScopedObject Ref(Object* object) { + return ScopedObject{object}; +} + +template +ScopedObject Adopt(Object* object) { + return ScopedObject{object, AdoptTag::kAdopted}; +} + +template +ScopedObject Adopt(typename Object::InteropCSibling* object) { + return Adopt(reinterpret_cast(object)); +} + +template +ScopedObject Create(CtorArgs&&... args) { + return ScopedObject{new Object(std::forward(args)...), + AdoptTag::kAdopted}; +} + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_OBJECT_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/object_unittests.cc b/engine/src/flutter/impeller/toolkit/interop/object_unittests.cc new file mode 100644 index 00000000000..01cb52989aa --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/object_unittests.cc @@ -0,0 +1,98 @@ +// 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/testing/testing.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop::testing { + +IMPELLER_DEFINE_HANDLE(FlagHandle); + +class FlagObject final + : public Object { + public: + explicit FlagObject(bool& destruction_flag) + : destruction_flag_(destruction_flag) { + FML_CHECK(!destruction_flag_) << "Destruction flag must be cleared."; + } + + ~FlagObject() { + FML_CHECK(!destruction_flag_) << "Already destructed."; + destruction_flag_ = true; + } + + private: + bool& destruction_flag_; +}; + +IMPELLER_DEFINE_HANDLE(TestHandle); + +class TestObject final + : public Object { + public: + TestObject(int arg1, double arg2, char arg3) + : arg1_(arg1), arg2_(arg2), arg3_(arg3) {} + + ~TestObject() = default; + + auto GetArg1() const { return arg1_; } + + auto GetArg2() const { return arg2_; } + + auto GetArg3() const { return arg3_; } + + private: + int arg1_ = {}; + double arg2_ = {}; + char arg3_ = {}; +}; + +TEST(InteropObjectTest, CanCreateScoped) { + bool destructed = false; + { + auto object = Adopt(new FlagObject(destructed)); // + } + ASSERT_TRUE(destructed); + + destructed = false; + { + auto object = Ref(new FlagObject(destructed)); + // New objects start with retain count of 1. + object->Release(); + } + ASSERT_TRUE(destructed); +} + +TEST(InteropObjectTest, CanCreate) { + auto object = Create(1, 1.3, 'c'); + ASSERT_EQ(object->GetArg1(), 1); + ASSERT_EQ(object->GetArg2(), 1.3); + ASSERT_EQ(object->GetArg3(), 'c'); +} + +TEST(InteropObjectTest, CanCopyAssignMove) { + auto o = Create(1, 2.3, 'd'); + ASSERT_EQ(o->GetRefCountForTests(), 1u); + { + auto o1 = o; // NOLINT(performance-unnecessary-copy-initialization) + ASSERT_EQ(o->GetRefCountForTests(), 2u); + auto o2 = o; // NOLINT(performance-unnecessary-copy-initialization) + ASSERT_EQ(o->GetRefCountForTests(), 3u); + auto o3 = o1; // NOLINT(performance-unnecessary-copy-initialization) + ASSERT_EQ(o->GetRefCountForTests(), 4u); + } + ASSERT_EQ(o->GetRefCountForTests(), 1u); + + { + auto o1(o); // NOLINT(performance-unnecessary-copy-initialization) + ASSERT_EQ(o->GetRefCountForTests(), 2u); + ASSERT_EQ(o1->GetRefCountForTests(), 2u); + } + + auto move_o = std::move(o); + ASSERT_EQ(move_o->GetRefCountForTests(), 1u); +} + +} // namespace impeller::interop::testing diff --git a/engine/src/flutter/impeller/toolkit/interop/paint.cc b/engine/src/flutter/impeller/toolkit/interop/paint.cc new file mode 100644 index 00000000000..7a0774905e9 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/paint.cc @@ -0,0 +1,61 @@ +// 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 "impeller/toolkit/interop/paint.h" + +namespace impeller::interop { + +Paint::Paint() = default; + +Paint::~Paint() = default; + +const flutter::DlPaint& Paint::GetPaint() const { + return paint_; +} + +void Paint::SetColor(flutter::DlColor color) { + paint_.setColor(color); +} + +void Paint::SetBlendMode(BlendMode mode) { + paint_.setBlendMode(ToDisplayListType(mode)); +} + +void Paint::SetDrawStyle(flutter::DlDrawStyle style) { + paint_.setDrawStyle(style); +} + +void Paint::SetStrokeCap(flutter::DlStrokeCap stroke_cap) { + paint_.setStrokeCap(stroke_cap); +} + +void Paint::SetStrokeJoin(flutter::DlStrokeJoin stroke_join) { + paint_.setStrokeJoin(stroke_join); +} + +void Paint::SetStrokeWidth(Scalar width) { + paint_.setStrokeWidth(width); +} + +void Paint::SetStrokeMiter(Scalar miter) { + paint_.setStrokeMiter(miter); +} + +void Paint::SetColorFilter(const ColorFilter& filter) { + paint_.setColorFilter(filter.GetColorFilter()); +} + +void Paint::SetColorSource(const ColorSource& source) { + paint_.setColorSource(source.GetColorSource()); +} + +void Paint::SetImageFilter(const ImageFilter& filter) { + paint_.setImageFilter(filter.GetImageFilter()); +} + +void Paint::SetMaskFilter(const MaskFilter& filter) { + paint_.setMaskFilter(filter.GetMaskFilter()); +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/paint.h b/engine/src/flutter/impeller/toolkit/interop/paint.h new file mode 100644 index 00000000000..863656b096a --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/paint.h @@ -0,0 +1,62 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_PAINT_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_PAINT_H_ + +#include "flutter/display_list/dl_color.h" +#include "flutter/display_list/dl_paint.h" +#include "impeller/geometry/color.h" +#include "impeller/toolkit/interop/color_filter.h" +#include "impeller/toolkit/interop/color_source.h" +#include "impeller/toolkit/interop/formats.h" +#include "impeller/toolkit/interop/image_filter.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/mask_filter.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class Paint final + : public Object { + public: + Paint(); + + ~Paint() override; + + Paint(const Paint&) = delete; + + Paint& operator=(const Paint&) = delete; + + const flutter::DlPaint& GetPaint() const; + + void SetColor(flutter::DlColor color); + + void SetBlendMode(BlendMode mode); + + void SetDrawStyle(flutter::DlDrawStyle style); + + void SetStrokeCap(flutter::DlStrokeCap stroke_cap); + + void SetStrokeJoin(flutter::DlStrokeJoin stroke_join); + + void SetStrokeWidth(Scalar width); + + void SetStrokeMiter(Scalar miter); + + void SetColorFilter(const ColorFilter& filter); + + void SetColorSource(const ColorSource& source); + + void SetImageFilter(const ImageFilter& filter); + + void SetMaskFilter(const MaskFilter& filter); + + private: + flutter::DlPaint paint_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_PAINT_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/path.cc b/engine/src/flutter/impeller/toolkit/interop/path.cc new file mode 100644 index 00000000000..a004a99ed61 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/path.cc @@ -0,0 +1,17 @@ +// 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 "impeller/toolkit/interop/path.h" + +namespace impeller::interop { + +Path::Path(const SkPath& path) : path_(path) {} + +Path::~Path() = default; + +const SkPath& Path::GetPath() const { + return path_; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/path.h b/engine/src/flutter/impeller/toolkit/interop/path.h new file mode 100644 index 00000000000..ddf96f91535 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/path.h @@ -0,0 +1,34 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_PATH_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_H_ + +#include "flutter/third_party/skia/include/core/SkPath.h" +#include "impeller/geometry/path.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class Path final + : public Object { + public: + explicit Path(const SkPath& path); + + ~Path(); + + Path(const Path&) = delete; + + Path& operator=(const Path&) = delete; + + const SkPath& GetPath() const; + + private: + SkPath path_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/path_builder.cc b/engine/src/flutter/impeller/toolkit/interop/path_builder.cc new file mode 100644 index 00000000000..a1620185d73 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/path_builder.cc @@ -0,0 +1,74 @@ +// 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 "impeller/toolkit/interop/path_builder.h" + +#include "impeller/toolkit/interop/formats.h" + +namespace impeller::interop { + +PathBuilder::PathBuilder() = default; + +PathBuilder::~PathBuilder() = default; + +void PathBuilder::MoveTo(const Point& point) { + builder_.moveTo(ToSkiaType(point)); +} + +void PathBuilder::LineTo(const Point& location) { + builder_.lineTo(ToSkiaType(location)); +} + +void PathBuilder::QuadraticCurveTo(const Point& control_point, + const Point& end_point) { + builder_.quadTo(ToSkiaType(control_point), ToSkiaType(end_point)); +} + +void PathBuilder::CubicCurveTo(const Point& control_point_1, + const Point& control_point_2, + const Point& end_point) { + builder_.cubicTo(ToSkiaType(control_point_1), // + ToSkiaType(control_point_2), // + ToSkiaType(end_point) // + ); +} + +void PathBuilder::AddRect(const Rect& rect) { + builder_.addRect(ToSkiaType(rect)); +} + +void PathBuilder::AddArc(const Rect& oval_bounds, + Degrees start_angle, + Degrees end_angle) { + builder_.addArc(ToSkiaType(oval_bounds), // + start_angle.degrees, // + end_angle.degrees - start_angle.degrees // sweep + ); +} + +void PathBuilder::AddOval(const Rect& oval_bounds) { + builder_.addOval(ToSkiaType(oval_bounds)); +} + +void PathBuilder::AddRoundedRect( + const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii) { + builder_.addRRect(ToSkiaType(rect, radii)); +} + +void PathBuilder::Close() { + builder_.close(); +} + +ScopedObject PathBuilder::TakePath(FillType fill) { + builder_.setFillType(ToSkiaType(fill)); + return Create(std::move(builder_)); +} + +ScopedObject PathBuilder::CopyPath(FillType fill) { + builder_.setFillType(ToSkiaType(fill)); + return Create(builder_); +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/path_builder.h b/engine/src/flutter/impeller/toolkit/interop/path_builder.h new file mode 100644 index 00000000000..1c9aa532b90 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/path_builder.h @@ -0,0 +1,60 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_PATH_BUILDER_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_BUILDER_H_ + +#include "flutter/third_party/skia/include/core/SkPath.h" +#include "impeller/geometry/path.h" +#include "impeller/geometry/path_builder.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" +#include "impeller/toolkit/interop/path.h" + +namespace impeller::interop { + +class PathBuilder final + : public Object { + public: + PathBuilder(); + + ~PathBuilder(); + + PathBuilder(const PathBuilder&) = delete; + + PathBuilder& operator=(const PathBuilder&) = delete; + + void MoveTo(const Point& point); + + void LineTo(const Point& location); + + void QuadraticCurveTo(const Point& control_point, const Point& end_point); + + void CubicCurveTo(const Point& control_point_1, + const Point& control_point_2, + const Point& end_point); + + void AddRect(const Rect& rect); + + void AddArc(const Rect& oval_bounds, Degrees start_angle, Degrees end_angle); + + void AddOval(const Rect& oval_bounds); + + void AddRoundedRect(const Rect& rect, + const impeller::PathBuilder::RoundingRadii& radii); + + void Close(); + + ScopedObject TakePath(FillType fill); + + ScopedObject CopyPath(FillType fill); + + private: + SkPath builder_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_BUILDER_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/playground_test.cc b/engine/src/flutter/impeller/toolkit/interop/playground_test.cc new file mode 100644 index 00000000000..f23a9276878 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/playground_test.cc @@ -0,0 +1,74 @@ +// 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 "impeller/toolkit/interop/playground_test.h" + +namespace impeller::interop::testing { + +PlaygroundTest::PlaygroundTest() = default; + +PlaygroundTest::~PlaygroundTest() = default; + +// |PlaygroundTest| +void PlaygroundTest::SetUp() { + ::impeller::PlaygroundTest::SetUp(); +} + +// |PlaygroundTest| +void PlaygroundTest::TearDown() { + ::impeller::PlaygroundTest::TearDown(); +} + +ScopedObject PlaygroundTest::CreateContext() const { + switch (GetBackend()) { + case PlaygroundBackend::kMetal: + FML_CHECK(false) << "Metal not yet implemented."; + return nullptr; + case PlaygroundBackend::kOpenGLES: { + Playground::GLProcAddressResolver playground_gl_proc_address_callback = + CreateGLProcAddressResolver(); + ImpellerProcAddressCallback gl_proc_address_callback = + [](const char* proc_name, void* user_data) -> void* { + return (*reinterpret_cast( + user_data))(proc_name); + }; + return Adopt(ImpellerContextCreateOpenGLESNew( + ImpellerGetVersion(), gl_proc_address_callback, + &playground_gl_proc_address_callback)); + } + case PlaygroundBackend::kVulkan: + FML_CHECK(false) << "Vulkan not yet implemented."; + return nullptr; + } + FML_UNREACHABLE(); +} + +bool PlaygroundTest::OpenPlaygroundHere(InteropPlaygroundCallback callback) { + auto context = GetInteropContext(); + if (!context) { + return false; + } + return Playground::OpenPlaygroundHere([&](RenderTarget& target) -> bool { + auto impeller_surface = std::make_shared(target); + auto surface = Create(*context.Get(), impeller_surface); + if (!surface) { + return false; + } + return callback(context, surface); + }); +} + +ScopedObject PlaygroundTest::GetInteropContext() { + if (interop_context_) { + return interop_context_; + } + auto context = Create(GetContext(), nullptr); + if (!context) { + return nullptr; + } + interop_context_ = std::move(context); + return interop_context_; +} + +} // namespace impeller::interop::testing diff --git a/engine/src/flutter/impeller/toolkit/interop/playground_test.h b/engine/src/flutter/impeller/toolkit/interop/playground_test.h new file mode 100644 index 00000000000..5c8eb84bab5 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/playground_test.h @@ -0,0 +1,48 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_PLAYGROUND_TEST_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_PLAYGROUND_TEST_H_ + +#include + +#include "impeller/playground/playground_test.h" +#include "impeller/toolkit/interop/context.h" +#include "impeller/toolkit/interop/surface.h" + +namespace impeller::interop::testing { + +class PlaygroundTest : public ::impeller::PlaygroundTest { + public: + PlaygroundTest(); + + // |PlaygroundTest| + ~PlaygroundTest() override; + + PlaygroundTest(const PlaygroundTest&) = delete; + + PlaygroundTest& operator=(const PlaygroundTest&) = delete; + + // |PlaygroundTest| + void SetUp() override; + + // |PlaygroundTest| + void TearDown() override; + + ScopedObject CreateContext() const; + + ScopedObject GetInteropContext(); + + using InteropPlaygroundCallback = + std::function& context, + const ScopedObject& surface)>; + bool OpenPlaygroundHere(InteropPlaygroundCallback callback); + + private: + ScopedObject interop_context_; +}; + +} // namespace impeller::interop::testing + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_PLAYGROUND_TEST_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/surface.cc b/engine/src/flutter/impeller/toolkit/interop/surface.cc new file mode 100644 index 00000000000..20a2f4c4188 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/surface.cc @@ -0,0 +1,81 @@ +// 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 "impeller/toolkit/interop/surface.h" + +#include "impeller/aiks/aiks_context.h" +#include "impeller/base/validation.h" +#include "impeller/display_list/dl_dispatcher.h" +#include "impeller/renderer/backend/gles/surface_gles.h" +#include "impeller/toolkit/interop/formats.h" + +namespace impeller::interop { + +Surface::Surface(Context& context, std::shared_ptr surface) + : context_(Ref(&context)), surface_(std::move(surface)) { + is_valid_ = + context_ && context_->IsValid() && surface_ && surface_->IsValid(); +} + +Surface::~Surface() = default; + +ScopedObject Surface::WrapFBO(Context& context, + uint64_t fbo, + PixelFormat color_format, + ISize size) { + if (context.GetContext()->GetBackendType() != + impeller::Context::BackendType::kOpenGLES) { + VALIDATION_LOG << "Context is not OpenGL ES based."; + return nullptr; + } + + auto impeller_surface = impeller::SurfaceGLES::WrapFBO( + context.GetContext(), []() { return true; }, fbo, color_format, size); + if (!impeller_surface || !impeller_surface->IsValid()) { + VALIDATION_LOG << "Could not wrap FBO as a surface"; + return nullptr; + } + + auto surface = Create(context, std::move(impeller_surface)); + if (!surface->IsValid()) { + VALIDATION_LOG << "Could not create valid surface."; + return nullptr; + } + return surface; +} + +bool Surface::IsValid() const { + return is_valid_; +} + +bool Surface::DrawDisplayList(const DisplayList& dl) const { + if (!IsValid() || !dl.IsValid()) { + return false; + } + + auto display_list = dl.GetDisplayList(); + auto& content_context = context_->GetAiksContext().GetContentContext(); + auto render_target = surface_->GetTargetRenderPassDescriptor(); + + const auto cull_rect = IRect::MakeSize(surface_->GetSize()); + auto skia_cull_rect = + SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight()); + impeller::TextFrameDispatcher collector(content_context, impeller::Matrix{}); + display_list->Dispatch(collector, skia_cull_rect); + + impeller::ExperimentalDlDispatcher impeller_dispatcher( + content_context, // + render_target, // + display_list->root_has_backdrop_filter(), // + display_list->max_root_blend_mode(), // + cull_rect // + ); + display_list->Dispatch(impeller_dispatcher, skia_cull_rect); + impeller_dispatcher.FinishRecording(); + content_context.GetLazyGlyphAtlas()->ResetTextFrames(); + content_context.GetTransientsBuffer().Reset(); + return true; +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/surface.h b/engine/src/flutter/impeller/toolkit/interop/surface.h new file mode 100644 index 00000000000..f489a5e5b77 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/surface.h @@ -0,0 +1,47 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_SURFACE_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_SURFACE_H_ + +#include + +#include "impeller/renderer/surface.h" +#include "impeller/toolkit/interop/context.h" +#include "impeller/toolkit/interop/dl.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class Surface final + : public Object { + public: + static ScopedObject WrapFBO(Context& context, + uint64_t fbo, + PixelFormat color_format, + ISize size); + + explicit Surface(Context& context, + std::shared_ptr surface); + + ~Surface() override; + + Surface(const Surface&) = delete; + + Surface& operator=(const Surface&) = delete; + + bool IsValid() const; + + bool DrawDisplayList(const DisplayList& dl) const; + + private: + ScopedObject context_; + std::shared_ptr surface_; + bool is_valid_ = false; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_SURFACE_H_ diff --git a/engine/src/flutter/impeller/toolkit/interop/texture.cc b/engine/src/flutter/impeller/toolkit/interop/texture.cc new file mode 100644 index 00000000000..d4edd587fe7 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/texture.cc @@ -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. + +#include "impeller/toolkit/interop/texture.h" + +namespace impeller::interop { + +Texture::Texture(const Context& context, const TextureDescriptor& descriptor) { + if (!context.IsValid()) { + return; + } + auto texture = + context.GetContext()->GetResourceAllocator()->CreateTexture(descriptor); + if (!texture || !texture->IsValid()) { + return; + } + texture_ = std::move(texture); +} + +Texture::~Texture() = default; + +bool Texture::IsValid() const { + return !!texture_; +} + +bool Texture::SetContents(const uint8_t* contents, uint64_t length) { + if (!IsValid()) { + return false; + } + return texture_->SetContents(contents, length); +} + +bool Texture::SetContents(std::shared_ptr contents) { + if (!IsValid()) { + return false; + } + return texture_->SetContents(std::move(contents)); +} + +sk_sp Texture::MakeImage() const { + return DlImageImpeller::Make(texture_); +} + +} // namespace impeller::interop diff --git a/engine/src/flutter/impeller/toolkit/interop/texture.h b/engine/src/flutter/impeller/toolkit/interop/texture.h new file mode 100644 index 00000000000..3a6c88b0f98 --- /dev/null +++ b/engine/src/flutter/impeller/toolkit/interop/texture.h @@ -0,0 +1,41 @@ +// 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_IMPELLER_TOOLKIT_INTEROP_TEXTURE_H_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_TEXTURE_H_ + +#include "impeller/core/texture.h" +#include "impeller/display_list/dl_image_impeller.h" +#include "impeller/toolkit/interop/context.h" +#include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/object.h" + +namespace impeller::interop { + +class Texture final + : public Object { + public: + explicit Texture(const Context& context, const TextureDescriptor& descriptor); + + ~Texture() override; + + Texture(const Texture&) = delete; + + Texture& operator=(const Texture&) = delete; + + bool IsValid() const; + + bool SetContents(const uint8_t* contents, uint64_t length); + + bool SetContents(std::shared_ptr contents); + + sk_sp MakeImage() const; + + private: + std::shared_ptr texture_; +}; + +} // namespace impeller::interop + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_TEXTURE_H_