[Impeller] Expose a single-header C API to Impellers Display-List layer. (flutter/engine#55238)

This (`impeller.h`) is a versioned, single-header, dependency-free, C API that exposes Display-Lists in almost their entirety.

The anticipated users of this API do not expect ABI or API stability guarantees at this time but those can be added between specific versions as the API matures.

Testing this API can be done via a playgrounds harness. One has been setup with rudimentary tests that will be filled out.

A simple C example (`example.c`) using GLFW with OpenGL ES has been setup. Only OpenGL ES has been exposed at this time but additional backend will be added.

This API is meant to be easy to bind to using automated tools for access in different languages and runtimes. Consequently, the API follows a strict convention for object naming, creating, and reference-counting.

* All typedefs and method names have the “Impeller” prefix.
* Most objects are reference counted. Methods ending with “New” return a new instance of the object with reference count of 1.
* Each object has a “Retain” and “Release” method to modify reference counts.

For instance, with Rust `bindgen`, the following invocation generates usable bindings:

```sh
bindgen impeller.h -o impeller.rs
  --no-layout-tests
  --rustified-enum “Impeller.*”
  --allowlist-item “Impeller.*”
```

It is expected that wrapped over these generated bindings will be written to make the usage more idiomatic. The C API itself is fairly verbose as well.

<img width="1107" alt="Screenshot 2024-09-12 at 2 55 14 PM" src="https://github.com/user-attachments/assets/e1532dba-487e-4af1-9442-1005a8f52d8d">
This commit is contained in:
Chinmay Garde 2024-09-18 10:02:16 -07:00 committed by GitHub
parent e545a006f8
commit e305ecf97a
47 changed files with 4320 additions and 13 deletions

View File

@ -210,6 +210,7 @@ group("unittests") {
public_deps += [
"//flutter/impeller:impeller_dart_unittests",
"//flutter/impeller:impeller_unittests",
"//flutter/impeller/toolkit/interop:example",
]
}

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -127,19 +127,7 @@ ShaderLibraryMappingsForPlayground() {
// |PlaygroundImpl|
std::shared_ptr<Context> 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<void*>(::glfwGetProcAddress(name));
};
auto gl = std::make_unique<ProcTableGLES>(resolver);
auto gl = std::make_unique<ProcTableGLES>(CreateGLProcAddressResolver());
if (!gl->IsValid()) {
FML_LOG(ERROR) << "Proc table when creating a playground was invalid.";
return nullptr;
@ -160,6 +148,23 @@ std::shared_ptr<Context> 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<void*>(::glfwGetProcAddress(name));
};
}
// |PlaygroundImpl|
PlaygroundImpl::WindowHandle PlaygroundImplGLES::GetWindowHandle() const {
return handle_.get();

View File

@ -38,6 +38,10 @@ class PlaygroundImplGLES final : public PlaygroundImpl {
std::unique_ptr<Surface> AcquireSurfaceFrame(
std::shared_ptr<Context> context) override;
// |PlaygroundImpl|
Playground::GLProcAddressResolver CreateGLProcAddressResolver()
const override;
PlaygroundImplGLES(const PlaygroundImplGLES&) = delete;
PlaygroundImplGLES& operator=(const PlaygroundImplGLES&) = delete;

View File

@ -513,4 +513,9 @@ bool Playground::WillRenderSomething() const {
return switches_.enable_playground;
}
Playground::GLProcAddressResolver Playground::CreateGLProcAddressResolver()
const {
return impl_->CreateGLProcAddressResolver();
}
} // namespace impeller

View File

@ -114,6 +114,9 @@ class Playground {
/// Returns true if `OpenPlaygroundHere` will actually render anything.
bool WillRenderSomething() const;
using GLProcAddressResolver = std::function<void*(const char* proc_name)>;
GLProcAddressResolver CreateGLProcAddressResolver() const;
protected:
const PlaygroundSwitches switches_;

View File

@ -66,4 +66,9 @@ Vector2 PlaygroundImpl::GetContentScale() const {
return scale;
}
Playground::GLProcAddressResolver PlaygroundImpl::CreateGLProcAddressResolver()
const {
return nullptr;
}
} // namespace impeller

View File

@ -5,6 +5,7 @@
#ifndef FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_IMPL_H_
#define FLUTTER_IMPELLER_PLAYGROUND_PLAYGROUND_IMPL_H_
#include <functional>
#include <memory>
#include "impeller/playground/playground.h"
@ -35,6 +36,8 @@ class PlaygroundImpl {
virtual fml::Status SetCapabilities(
const std::shared_ptr<Capabilities>& capabilities) = 0;
virtual Playground::GLProcAddressResolver CreateGLProcAddressResolver() const;
protected:
const PlaygroundSwitches switches_;

View File

@ -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",
]
}

View File

@ -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> ColorFilter::MakeBlend(Color color, BlendMode mode) {
auto filter = flutter::DlBlendColorFilter::Make(ToDisplayListType(color),
ToDisplayListType(mode));
if (!filter) {
return nullptr;
}
return Create<ColorFilter>(std::move(filter));
}
ScopedObject<ColorFilter> ColorFilter::MakeMatrix(const float matrix[20]) {
auto filter = flutter::DlMatrixColorFilter::Make(matrix);
if (!filter) {
return nullptr;
}
return Create<ColorFilter>(std::move(filter));
}
ColorFilter::ColorFilter(std::shared_ptr<flutter::DlColorFilter> filter)
: filter_(std::move(filter)) {}
ColorFilter::~ColorFilter() = default;
const std::shared_ptr<flutter::DlColorFilter>& ColorFilter::GetColorFilter()
const {
return filter_;
}
} // namespace impeller::interop

View File

@ -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<ColorFilter,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerColorFilter)> {
public:
static ScopedObject<ColorFilter> MakeBlend(Color color, BlendMode mode);
static ScopedObject<ColorFilter> MakeMatrix(const float matrix[20]);
explicit ColorFilter(std::shared_ptr<flutter::DlColorFilter> filter);
~ColorFilter() override;
ColorFilter(const ColorFilter&) = delete;
ColorFilter& operator=(const ColorFilter&) = delete;
const std::shared_ptr<flutter::DlColorFilter>& GetColorFilter() const;
private:
std::shared_ptr<flutter::DlColorFilter> filter_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_COLOR_FILTER_H_

View File

@ -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> ColorSource::MakeLinearGradient(
const Point& start_point,
const Point& end_point,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& 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<ColorSource>(std::move(dl_filter));
}
ScopedObject<ColorSource> ColorSource::MakeRadialGradient(
const Point& center,
Scalar radius,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& 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<ColorSource>(std::move(dl_filter));
}
ScopedObject<ColorSource> ColorSource::MakeConicalGradient(
const Point& start_center,
Scalar start_radius,
const Point& end_center,
Scalar end_radius,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& 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<ColorSource>(std::move(dl_filter));
}
ScopedObject<ColorSource> ColorSource::MakeSweepGradient(
const Point& center,
Scalar start,
Scalar end,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& 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<ColorSource>(std::move(dl_filter));
}
ColorSource::ColorSource(std::shared_ptr<flutter::DlColorSource> source)
: color_source_(std::move(source)) {}
ColorSource::~ColorSource() = default;
bool ColorSource::IsValid() const {
return !!color_source_;
}
const std::shared_ptr<flutter::DlColorSource>& ColorSource::GetColorSource()
const {
return color_source_;
}
} // namespace impeller::interop

View File

@ -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 <vector>
#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<ColorSource,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerColorSource)> {
public:
static ScopedObject<ColorSource> MakeLinearGradient(
const Point& start_point,
const Point& end_point,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& stops,
flutter::DlTileMode tile_mode,
const Matrix& transformation);
static ScopedObject<ColorSource> MakeRadialGradient(
const Point& center,
Scalar radius,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& stops,
flutter::DlTileMode tile_mode,
const Matrix& transformation);
static ScopedObject<ColorSource> MakeConicalGradient(
const Point& start_center,
Scalar start_radius,
const Point& end_center,
Scalar end_radius,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& stops,
flutter::DlTileMode tile_mode,
const Matrix& transformation);
static ScopedObject<ColorSource> MakeSweepGradient(
const Point& center,
Scalar start,
Scalar end,
const std::vector<flutter::DlColor>& colors,
const std::vector<Scalar>& stops,
flutter::DlTileMode tile_mode,
const Matrix& transformation);
explicit ColorSource(std::shared_ptr<flutter::DlColorSource> source);
~ColorSource() override;
ColorSource(const ColorSource&) = delete;
ColorSource& operator=(const ColorSource&) = delete;
bool IsValid() const;
const std::shared_ptr<flutter::DlColorSource>& GetColorSource() const;
private:
std::shared_ptr<flutter::DlColorSource> color_source_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_COLOR_SOURCE_H_

View File

@ -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 <thread>
#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<impeller::Context> context,
std::shared_ptr<BackendData> 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<impeller::Context> 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> Context::CreateOpenGLES(
std::function<void*(const char* gl_proc_name)> proc_address_callback) {
#if IMPELLER_ENABLE_OPENGLES
auto proc_table = std::make_unique<ProcTableGLES>(
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<std::shared_ptr<fml::Mapping>> shader_mappings = {
std::make_shared<fml::NonOwnedMapping>(
impeller_entity_shaders_gles_data,
impeller_entity_shaders_gles_length),
std::make_shared<fml::NonOwnedMapping>(
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<ReactorWorker>();
auto worker_id = impeller_context->AddReactorWorker(reactor_worker);
if (!worker_id.has_value()) {
VALIDATION_LOG << "Could not add reactor worker.";
return {};
}
auto context =
Create<Context>(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

View File

@ -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 <functional>
#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<Context, IMPELLER_INTERNAL_HANDLE_NAME(ImpellerContext)> {
public:
class BackendData;
static ScopedObject<Context> CreateOpenGLES(
std::function<void*(const char* gl_proc_name)> proc_address_callback);
explicit Context(std::shared_ptr<impeller::Context> context,
std::shared_ptr<BackendData> backend_data);
~Context() override;
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
bool IsValid() const;
std::shared_ptr<impeller::Context> GetContext() const;
AiksContext& GetAiksContext();
private:
impeller::AiksContext context_;
std::shared_ptr<BackendData> backend_data_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_CONTEXT_H_

View File

@ -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<flutter::DisplayList> display_list)
: display_list_(std::move(display_list)) {}
DisplayList::~DisplayList() = default;
bool DisplayList::IsValid() const {
return !!display_list_;
}
const sk_sp<flutter::DisplayList> DisplayList::GetDisplayList() const {
return display_list_;
}
} // namespace impeller::interop

View File

@ -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<DisplayList,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerDisplayList)> {
public:
explicit DisplayList(sk_sp<flutter::DisplayList> display_list);
~DisplayList() override;
DisplayList(const DisplayList&) = delete;
DisplayList& operator=(const DisplayList&) = delete;
bool IsValid() const;
const sk_sp<flutter::DisplayList> GetDisplayList() const;
private:
sk_sp<flutter::DisplayList> display_list_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_DL_H_

View File

@ -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<DisplayList> DisplayListBuilder::Build() {
return Create<DisplayList>(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

View File

@ -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<DisplayListBuilder,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerDisplayListBuilder)> {
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<DisplayList> Build();
private:
flutter::DisplayListBuilder builder_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_DL_BUILDER_H_

View File

@ -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 <assert.h>
#include <stdio.h>
#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;
}

View File

@ -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

View File

@ -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 <vector>
#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<SkRect> 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 <class SkiaType, class OtherType>
std::vector<SkiaType> ToSkiaType(const std::vector<OtherType>& other_vec) {
std::vector<SkiaType> 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 <class DlType, class OtherType>
std::vector<DlType> ToDisplayListType(const std::vector<OtherType>& other_vec) {
std::vector<DlType> 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_

View File

@ -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<const flutter::DlImageFilter> filter)
: filter_(std::move(filter)) {}
ImageFilter::~ImageFilter() = default;
ScopedObject<ImageFilter> 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<ImageFilter>(std::move(filter));
}
ScopedObject<ImageFilter> ImageFilter::MakeDilate(Scalar x_radius,
Scalar y_radius) {
auto filter = flutter::DlDilateImageFilter::Make(x_radius, y_radius);
if (!filter) {
return nullptr;
}
return Create<ImageFilter>(std::move(filter));
}
ScopedObject<ImageFilter> ImageFilter::MakeErode(Scalar x_radius,
Scalar y_radius) {
auto filter = flutter::DlErodeImageFilter::Make(x_radius, y_radius);
if (!filter) {
return nullptr;
}
return Create<ImageFilter>(std::move(filter));
}
ScopedObject<ImageFilter> ImageFilter::MakeMatrix(
const Matrix& matrix,
flutter::DlImageSampling sampling) {
auto filter =
flutter::DlMatrixImageFilter::Make(ToSkMatrix(matrix), sampling);
if (!filter) {
return nullptr;
}
return Create<ImageFilter>(std::move(filter));
}
ScopedObject<ImageFilter> ImageFilter::MakeCompose(const ImageFilter& outer,
const ImageFilter& inner) {
auto filter = flutter::DlComposeImageFilter::Make(outer.GetImageFilter(),
inner.GetImageFilter());
if (!filter) {
return nullptr;
}
return Create<ImageFilter>(std::move(filter));
}
const std::shared_ptr<const flutter::DlImageFilter>&
ImageFilter::GetImageFilter() const {
return filter_;
}
} // namespace impeller::interop

View File

@ -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<ImageFilter,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerImageFilter)> {
public:
static ScopedObject<ImageFilter> MakeBlur(Scalar x_sigma,
Scalar y_sigma,
flutter::DlTileMode tile_mode);
static ScopedObject<ImageFilter> MakeDilate(Scalar x_radius, Scalar y_radius);
static ScopedObject<ImageFilter> MakeErode(Scalar x_radius, Scalar y_radius);
static ScopedObject<ImageFilter> MakeMatrix(
const Matrix& matrix,
flutter::DlImageSampling sampling);
static ScopedObject<ImageFilter> MakeCompose(const ImageFilter& outer,
const ImageFilter& inner);
explicit ImageFilter(std::shared_ptr<const flutter::DlImageFilter> filter);
~ImageFilter() override;
ImageFilter(const ImageFilter&) = delete;
ImageFilter& operator=(const ImageFilter&) = delete;
const std::shared_ptr<const flutter::DlImageFilter>& GetImageFilter() const;
private:
std::shared_ptr<const flutter::DlImageFilter> filter_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMAGE_FILTER_H_

View File

@ -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 <sstream>
#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<cxx_type*>(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<DisplayListBuilder>(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<PathBuilder>().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<Paint>().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<Texture>(*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<fml::NonOwnedMapping>(
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<flutter::DlColor>, std::vector<Scalar>>
ParseColorsAndStops(uint32_t stop_count,
const ImpellerColor* colors,
const float* stops) {
if (stop_count == 0) {
return {};
}
std::pair<std::vector<flutter::DlColor>, std::vector<Scalar>> 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

View File

@ -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 <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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_

View File

@ -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.

View File

@ -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<Surface>(ImpellerSurfaceCreateWrappedFBONew(
context.GetC(), //
0u, //
ImpellerPixelFormat::kImpellerPixelFormatRGBA8888, //
&size) //
);
ASSERT_TRUE(surface);
}
TEST_P(InteropPlaygroundTest, CanDrawRect) {
auto builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
auto paint = Adopt<Paint>(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<DisplayList>(
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<Texture>(ImpellerTextureCreateWithContentsNew(
context.GetC(), &desc, &mapping, nullptr));
ASSERT_TRUE(texture);
auto builder =
Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
ImpellerPoint point = {100, 100};
ImpellerDisplayListBuilderDrawTexture(builder.GetC(), texture.GetC(), &point,
kImpellerTextureSamplingLinear,
nullptr);
auto dl = Adopt<DisplayList>(
ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
ASSERT_TRUE(
OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
return true;
}));
}
} // namespace impeller::interop::testing

View File

@ -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> MaskFilter::MakeBlur(flutter::DlBlurStyle style,
float sigma) {
auto filter = flutter::DlBlurMaskFilter::Make(style, sigma);
if (!filter) {
return nullptr;
}
return Create<MaskFilter>(std::move(filter));
}
MaskFilter::MaskFilter(std::shared_ptr<flutter::DlMaskFilter> mask_filter)
: mask_filter_(std::move(mask_filter)) {}
MaskFilter::~MaskFilter() = default;
const std::shared_ptr<flutter::DlMaskFilter>& MaskFilter::GetMaskFilter()
const {
return mask_filter_;
}
} // namespace impeller::interop

View File

@ -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<MaskFilter,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerMaskFilter)> {
public:
static ScopedObject<MaskFilter> MakeBlur(flutter::DlBlurStyle style,
float sigma);
explicit MaskFilter(std::shared_ptr<flutter::DlMaskFilter> mask_filter);
~MaskFilter() override;
MaskFilter(const MaskFilter&) = delete;
MaskFilter& operator=(const MaskFilter&) = delete;
const std::shared_ptr<flutter::DlMaskFilter>& GetMaskFilter() const;
public:
std::shared_ptr<flutter::DlMaskFilter> mask_filter_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_MASK_FILTER_H_

View File

@ -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

View File

@ -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 <atomic>
#include <utility>
#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<ObjectBase*>(ptr)->Retain();
}
}
static void SafeRelease(void* ptr) {
if (ptr) {
reinterpret_cast<ObjectBase*>(ptr)->Release();
}
}
uint64_t GetRefCountForTests() const { return ref_count_; }
private:
std::atomic_uint64_t ref_count_ = {1u};
};
template <typename Clasz, typename CSibling>
class Object : public ObjectBase {
public:
using InteropClass = Clasz;
using InteropCSibling = CSibling;
};
enum class AdoptTag {
kAdopted,
};
template <typename Object>
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<typename Object::InteropCSibling*>(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<typename Object::InteropCSibling*>(to_leak);
}
private:
Object* object_ = nullptr;
void Release() {
if (object_) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDelete)
object_->Release();
object_ = nullptr;
}
}
};
template <typename Object>
ScopedObject<Object> Ref(Object* object) {
return ScopedObject<Object>{object};
}
template <typename Object>
ScopedObject<Object> Adopt(Object* object) {
return ScopedObject<Object>{object, AdoptTag::kAdopted};
}
template <typename Object>
ScopedObject<Object> Adopt(typename Object::InteropCSibling* object) {
return Adopt(reinterpret_cast<Object*>(object));
}
template <typename Object, typename... CtorArgs>
ScopedObject<Object> Create(CtorArgs&&... args) {
return ScopedObject<Object>{new Object(std::forward<CtorArgs>(args)...),
AdoptTag::kAdopted};
}
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_OBJECT_H_

View File

@ -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<FlagObject, IMPELLER_INTERNAL_HANDLE_NAME(FlagHandle)> {
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<TestObject, IMPELLER_INTERNAL_HANDLE_NAME(TestHandle)> {
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<TestObject>(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<TestObject>(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

View File

@ -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

View File

@ -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<Paint, IMPELLER_INTERNAL_HANDLE_NAME(ImpellerPaint)> {
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_

View File

@ -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

View File

@ -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<Path, IMPELLER_INTERNAL_HANDLE_NAME(ImpellerPath)> {
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_

View File

@ -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<Path> PathBuilder::TakePath(FillType fill) {
builder_.setFillType(ToSkiaType(fill));
return Create<Path>(std::move(builder_));
}
ScopedObject<Path> PathBuilder::CopyPath(FillType fill) {
builder_.setFillType(ToSkiaType(fill));
return Create<Path>(builder_);
}
} // namespace impeller::interop

View File

@ -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<PathBuilder,
IMPELLER_INTERNAL_HANDLE_NAME(ImpellerPathBuilder)> {
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<Path> TakePath(FillType fill);
ScopedObject<Path> CopyPath(FillType fill);
private:
SkPath builder_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_BUILDER_H_

View File

@ -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<Context> 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<Playground::GLProcAddressResolver*>(
user_data))(proc_name);
};
return Adopt<Context>(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<impeller::Surface>(target);
auto surface = Create<Surface>(*context.Get(), impeller_surface);
if (!surface) {
return false;
}
return callback(context, surface);
});
}
ScopedObject<Context> PlaygroundTest::GetInteropContext() {
if (interop_context_) {
return interop_context_;
}
auto context = Create<Context>(GetContext(), nullptr);
if (!context) {
return nullptr;
}
interop_context_ = std::move(context);
return interop_context_;
}
} // namespace impeller::interop::testing

View File

@ -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 <functional>
#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<Context> CreateContext() const;
ScopedObject<Context> GetInteropContext();
using InteropPlaygroundCallback =
std::function<bool(const ScopedObject<Context>& context,
const ScopedObject<Surface>& surface)>;
bool OpenPlaygroundHere(InteropPlaygroundCallback callback);
private:
ScopedObject<Context> interop_context_;
};
} // namespace impeller::interop::testing
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_PLAYGROUND_TEST_H_

View File

@ -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<impeller::Surface> surface)
: context_(Ref(&context)), surface_(std::move(surface)) {
is_valid_ =
context_ && context_->IsValid() && surface_ && surface_->IsValid();
}
Surface::~Surface() = default;
ScopedObject<Surface> 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<Surface>(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

View File

@ -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 <memory>
#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<Surface, IMPELLER_INTERNAL_HANDLE_NAME(ImpellerSurface)> {
public:
static ScopedObject<Surface> WrapFBO(Context& context,
uint64_t fbo,
PixelFormat color_format,
ISize size);
explicit Surface(Context& context,
std::shared_ptr<impeller::Surface> surface);
~Surface() override;
Surface(const Surface&) = delete;
Surface& operator=(const Surface&) = delete;
bool IsValid() const;
bool DrawDisplayList(const DisplayList& dl) const;
private:
ScopedObject<Context> context_;
std::shared_ptr<impeller::Surface> surface_;
bool is_valid_ = false;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_SURFACE_H_

View File

@ -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<const fml::Mapping> contents) {
if (!IsValid()) {
return false;
}
return texture_->SetContents(std::move(contents));
}
sk_sp<DlImageImpeller> Texture::MakeImage() const {
return DlImageImpeller::Make(texture_);
}
} // namespace impeller::interop

View File

@ -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<Texture, IMPELLER_INTERNAL_HANDLE_NAME(ImpellerTexture)> {
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<const fml::Mapping> contents);
sk_sp<DlImageImpeller> MakeImage() const;
private:
std::shared_ptr<impeller::Texture> texture_;
};
} // namespace impeller::interop
#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_TEXTURE_H_