[Impeller] Refactor SolidFill to use Path/Cover Geometry classes (flutter/engine#36661)

This commit is contained in:
Jonah Williams
2022-10-07 19:20:35 -07:00
committed by GitHub
parent c43dbd3ffc
commit 3a20231ba0
23 changed files with 350 additions and 195 deletions

View File

@@ -1210,8 +1210,6 @@ FILE: ../../../flutter/impeller/entity/contents/rrect_shadow_contents.cc
FILE: ../../../flutter/impeller/entity/contents/rrect_shadow_contents.h
FILE: ../../../flutter/impeller/entity/contents/solid_color_contents.cc
FILE: ../../../flutter/impeller/entity/contents/solid_color_contents.h
FILE: ../../../flutter/impeller/entity/contents/solid_fill_utils.cc
FILE: ../../../flutter/impeller/entity/contents/solid_fill_utils.h
FILE: ../../../flutter/impeller/entity/contents/solid_stroke_contents.cc
FILE: ../../../flutter/impeller/entity/contents/solid_stroke_contents.h
FILE: ../../../flutter/impeller/entity/contents/sweep_gradient_contents.cc

View File

@@ -209,7 +209,7 @@ void Canvas::DrawCircle(Point center, Scalar radius, Paint paint) {
void Canvas::ClipPath(Path path, Entity::ClipOperation clip_op) {
auto contents = std::make_shared<ClipContents>();
contents->SetPath(std::move(path));
contents->SetGeometry(Geometry::MakePath(std::move(path)));
contents->SetClipOperation(clip_op);
Entity entity;

View File

@@ -5,6 +5,7 @@
#include "impeller/aiks/paint.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/contents/solid_stroke_contents.h"
#include "impeller/entity/geometry.h"
namespace impeller {
@@ -13,18 +14,18 @@ std::shared_ptr<Contents> Paint::CreateContentsForEntity(Path path,
if (color_source.has_value()) {
auto& source = color_source.value();
auto contents = source();
contents->SetPath(std::move(path));
contents->SetGeometry(cover ? Geometry::MakeCover()
: Geometry::MakePath(std::move(path)));
contents->SetAlpha(color.alpha);
contents->SetCover(cover);
return contents;
}
switch (style) {
case Style::kFill: {
auto solid_color = std::make_shared<SolidColorContents>();
solid_color->SetPath(std::move(path));
solid_color->SetGeometry(cover ? Geometry::MakeCover()
: Geometry::MakePath(std::move(path)));
solid_color->SetColor(color);
solid_color->SetCover(cover);
return solid_color;
}
case Style::kStroke: {

View File

@@ -115,8 +115,6 @@ impeller_component("entity") {
"contents/rrect_shadow_contents.h",
"contents/solid_color_contents.cc",
"contents/solid_color_contents.h",
"contents/solid_fill_utils.cc",
"contents/solid_fill_utils.h",
"contents/solid_stroke_contents.cc",
"contents/solid_stroke_contents.h",
"contents/sweep_gradient_contents.cc",

View File

@@ -7,9 +7,7 @@
#include "fml/logging.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/vertex_buffer_builder.h"
@@ -24,8 +22,8 @@ ClipContents::ClipContents() = default;
ClipContents::~ClipContents() = default;
void ClipContents::SetPath(Path path) {
path_ = std::move(path);
void ClipContents::SetGeometry(std::unique_ptr<Geometry> geometry) {
geometry_ = std::move(geometry);
}
void ClipContents::SetClipOperation(Entity::ClipOperation clip_op) {
@@ -52,8 +50,7 @@ Contents::StencilCoverage ClipContents::GetStencilCoverage(
return {
.type = StencilCoverage::Type::kAppend,
.coverage = current_stencil_coverage->Intersection(
path_.GetTransformedBoundingBox(entity.GetTransformation())
.value()),
geometry_->GetCoverage(entity.GetTransformation()).value()),
};
}
FML_UNREACHABLE();
@@ -119,9 +116,14 @@ bool ClipContents::Render(const ContentContext& renderer,
}
cmd.pipeline = renderer.GetClipPipeline(options);
cmd.BindVertices(CreateSolidFillVertices(renderer.GetTessellator(), path_,
pass.GetTransientsBuffer()));
auto& host_buffer = pass.GetTransientsBuffer();
auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result = geometry_->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();
VS::BindVertInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info));

View File

@@ -11,6 +11,7 @@
#include "flutter/fml/macros.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/geometry.h"
namespace impeller {
@@ -20,7 +21,7 @@ class ClipContents final : public Contents {
~ClipContents();
void SetPath(Path path);
void SetGeometry(std::unique_ptr<Geometry> geometry);
void SetClipOperation(Entity::ClipOperation clip_op);
@@ -42,7 +43,7 @@ class ClipContents final : public Contents {
RenderPass& pass) const override;
private:
Path path_;
std::unique_ptr<Geometry> geometry_;
Entity::ClipOperation clip_op_ = Entity::ClipOperation::kIntersect;
FML_DISALLOW_COPY_AND_ASSIGN(ClipContents);

View File

@@ -13,12 +13,12 @@ ColorSourceContents::ColorSourceContents() = default;
ColorSourceContents::~ColorSourceContents() = default;
void ColorSourceContents::SetPath(Path path) {
path_ = path;
void ColorSourceContents::SetGeometry(std::unique_ptr<Geometry> geometry) {
geometry_ = std::move(geometry);
}
const Path& ColorSourceContents::GetPath() const {
return path_;
const std::unique_ptr<Geometry>& ColorSourceContents::GetGeometry() const {
return geometry_;
}
void ColorSourceContents::SetAlpha(Scalar alpha) {
@@ -37,17 +37,9 @@ const Matrix& ColorSourceContents::GetInverseMatrix() const {
return inverse_matrix_;
}
void ColorSourceContents::SetCover(bool cover) {
cover_ = cover;
}
bool ColorSourceContents::GetCover() const {
return cover_;
}
std::optional<Rect> ColorSourceContents::GetCoverage(
const Entity& entity) const {
return path_.GetTransformedBoundingBox(entity.GetTransformation());
return geometry_->GetCoverage(entity.GetTransformation());
};
bool ColorSourceContents::ShouldRender(
@@ -56,7 +48,7 @@ bool ColorSourceContents::ShouldRender(
if (!stencil_coverage.has_value()) {
return false;
}
return cover_ || Contents::ShouldRender(entity, stencil_coverage);
return Contents::ShouldRender(entity, stencil_coverage);
}
} // namespace impeller

View File

@@ -6,6 +6,7 @@
#include "flutter/fml/macros.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/geometry.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/path.h"
@@ -17,14 +18,12 @@ class ColorSourceContents : public Contents {
~ColorSourceContents() override;
void SetPath(Path path);
void SetGeometry(std::unique_ptr<Geometry> geometry);
void SetMatrix(Matrix matrix);
void SetAlpha(Scalar alpha);
void SetCover(bool cover);
// |Contents|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
@@ -33,19 +32,16 @@ class ColorSourceContents : public Contents {
const std::optional<Rect>& stencil_coverage) const override;
protected:
const Path& GetPath() const;
const std::unique_ptr<Geometry>& GetGeometry() const;
const Matrix& GetInverseMatrix() const;
Scalar GetAlpha() const;
bool GetCover() const;
private:
Path path_;
std::unique_ptr<Geometry> geometry_;
Matrix inverse_matrix_;
Scalar alpha_ = 1.0;
bool cover_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(ColorSourceContents);
};

View File

@@ -78,6 +78,9 @@ bool Contents::ShouldRender(const Entity& entity,
if (!coverage.has_value()) {
return false;
}
if (coverage == Rect::MakeMaximum()) {
return true;
}
return stencil_coverage->IntersectsWithRect(coverage.value());
}

View File

@@ -229,9 +229,10 @@ static std::optional<Snapshot> PipelineBlend(
if (foreground_color.has_value()) {
auto contents = std::make_shared<SolidColorContents>();
contents->SetPath(PathBuilder{}
.AddRect(Rect::MakeSize(pass.GetRenderTargetSize()))
.TakePath());
contents->SetGeometry(Geometry::MakePath(
PathBuilder{}
.AddRect(Rect::MakeSize(pass.GetRenderTargetSize()))
.TakePath()));
contents->SetColor(foreground_color.value());
Entity foreground_entity;

View File

@@ -7,9 +7,7 @@
#include "flutter/fml/logging.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/gradient_generator.h"
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
@@ -77,13 +75,14 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
cmd.pipeline = renderer.GetLinearGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(CreateSolidFillVertices(
renderer.GetTessellator(),
GetCover()
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: GetPath(),
pass.GetTransientsBuffer()));
cmd.primitive_type = PrimitiveType::kTriangle;
auto& host_buffer = pass.GetTransientsBuffer();
auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result = GetGeometry()->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
FS::BindGradientInfo(
cmd, pass.GetTransientsBuffer().EmplaceUniform(gradient_info));
SamplerDescriptor sampler_desc;

View File

@@ -7,9 +7,8 @@
#include "flutter/fml/logging.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/gradient_generator.h"
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/entity/geometry.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
@@ -76,13 +75,13 @@ bool RadialGradientContents::Render(const ContentContext& renderer,
cmd.pipeline = renderer.GetRadialGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(CreateSolidFillVertices(
renderer.GetTessellator(),
GetCover()
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: GetPath(),
pass.GetTransientsBuffer()));
cmd.primitive_type = PrimitiveType::kTriangle;
auto& host_buffer = pass.GetTransientsBuffer();
auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result = GetGeometry()->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
FS::BindGradientInfo(
cmd, pass.GetTransientsBuffer().EmplaceUniform(gradient_info));
SamplerDescriptor sampler_desc;

View File

@@ -5,10 +5,8 @@
#include "solid_color_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/render_pass.h"
namespace impeller {
@@ -25,12 +23,8 @@ const Color& SolidColorContents::GetColor() const {
return color_;
}
void SolidColorContents::SetPath(Path path) {
path_ = std::move(path);
}
void SolidColorContents::SetCover(bool cover) {
cover_ = cover;
void SolidColorContents::SetGeometry(std::unique_ptr<Geometry> geometry) {
geometry_ = std::move(geometry);
}
std::optional<Rect> SolidColorContents::GetCoverage(
@@ -38,7 +32,10 @@ std::optional<Rect> SolidColorContents::GetCoverage(
if (color_.IsTransparent()) {
return std::nullopt;
}
return path_.GetTransformedBoundingBox(entity.GetTransformation());
if (geometry_ == nullptr) {
return std::nullopt;
}
return geometry_->GetCoverage(entity.GetTransformation());
};
bool SolidColorContents::ShouldRender(
@@ -47,7 +44,7 @@ bool SolidColorContents::ShouldRender(
if (!stencil_coverage.has_value()) {
return false;
}
return cover_ || Contents::ShouldRender(entity, stencil_coverage);
return Contents::ShouldRender(entity, stencil_coverage);
}
bool SolidColorContents::Render(const ContentContext& renderer,
@@ -62,12 +59,13 @@ bool SolidColorContents::Render(const ContentContext& renderer,
renderer.GetSolidFillPipeline(OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(CreateSolidFillVertices(
renderer.GetTessellator(),
cover_
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: path_,
pass.GetTransientsBuffer()));
auto& host_buffer = pass.GetTransientsBuffer();
auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result = geometry_->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
VS::VertInfo vert_info;
vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
@@ -78,8 +76,6 @@ bool SolidColorContents::Render(const ContentContext& renderer,
frag_info.color = color_.Premultiply();
FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));
cmd.primitive_type = PrimitiveType::kTriangle;
if (!pass.AddCommand(std::move(cmd))) {
return false;
}
@@ -90,7 +86,7 @@ bool SolidColorContents::Render(const ContentContext& renderer,
std::unique_ptr<SolidColorContents> SolidColorContents::Make(Path path,
Color color) {
auto contents = std::make_unique<SolidColorContents>();
contents->SetPath(std::move(path));
contents->SetGeometry(Geometry::MakePath(std::move(path)));
contents->SetColor(color);
return contents;
}

View File

@@ -10,6 +10,7 @@
#include "flutter/fml/macros.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/geometry.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/path.h"
@@ -27,9 +28,7 @@ class SolidColorContents final : public Contents {
static std::unique_ptr<SolidColorContents> Make(Path path, Color color);
void SetPath(Path path);
void SetCover(bool cover);
void SetGeometry(std::unique_ptr<Geometry> geometry);
void SetColor(Color color);
@@ -48,8 +47,7 @@ class SolidColorContents final : public Contents {
RenderPass& pass) const override;
private:
Path path_;
bool cover_ = false;
std::unique_ptr<Geometry> geometry_;
Color color_;

View File

@@ -1,36 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/geometry/path.h"
#include "impeller/renderer/device_buffer.h"
#include "impeller/renderer/host_buffer.h"
#include "impeller/tessellator/tessellator.h"
namespace impeller {
VertexBuffer CreateSolidFillVertices(std::shared_ptr<Tessellator> tessellator,
const Path& path,
HostBuffer& buffer) {
VertexBuffer vertex_buffer;
auto tesselation_result = tessellator->TessellateBuilder(
path.GetFillType(), path.CreatePolyline(),
[&vertex_buffer, &buffer](const float* vertices, size_t vertices_count,
const uint16_t* indices, size_t indices_count) {
vertex_buffer.vertex_buffer = buffer.Emplace(
vertices, vertices_count * sizeof(float), alignof(float));
vertex_buffer.index_buffer = buffer.Emplace(
indices, indices_count * sizeof(uint16_t), alignof(uint16_t));
vertex_buffer.index_count = indices_count;
vertex_buffer.index_type = IndexType::k16bit;
return true;
});
if (tesselation_result != Tessellator::Result::kSuccess) {
return {};
}
return vertex_buffer;
}
} // namespace impeller

View File

@@ -1,28 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "impeller/renderer/vertex_buffer.h"
namespace impeller {
class Tessellator;
class Path;
class HostBuffer;
/**
* @brief Populate a VertexBuffer with solid fill vertices created by
* tessellating an input path.
*
* @param tessellator The tessellator
* @param path The path to be tessellated
* @param buffer The transient buffer
* @return VertexBuffer A populated vertex buffer if successful, otherwise
* empty.
*/
VertexBuffer CreateSolidFillVertices(std::shared_ptr<Tessellator> tessellator,
const Path& path,
HostBuffer& buffer);
} // namespace impeller

View File

@@ -7,9 +7,7 @@
#include "flutter/fml/logging.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/gradient_generator.h"
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
@@ -83,13 +81,13 @@ bool SweepGradientContents::Render(const ContentContext& renderer,
cmd.pipeline = renderer.GetSweepGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(CreateSolidFillVertices(
renderer.GetTessellator(),
GetCover()
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: GetPath(),
pass.GetTransientsBuffer()));
cmd.primitive_type = PrimitiveType::kTriangle;
auto& host_buffer = pass.GetTransientsBuffer();
auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result = GetGeometry()->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
FS::BindGradientInfo(
cmd, pass.GetTransientsBuffer().EmplaceUniform(gradient_info));
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));

View File

@@ -5,7 +5,7 @@
#include "impeller/entity/contents/tiled_texture_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/solid_fill_utils.h"
#include "impeller/entity/geometry.h"
#include "impeller/entity/tiled_texture_fill.frag.h"
#include "impeller/entity/tiled_texture_fill.vert.h"
#include "impeller/geometry/path_builder.h"
@@ -67,12 +67,12 @@ bool TiledTextureContents::Render(const ContentContext& renderer,
cmd.pipeline =
renderer.GetTiledTexturePipeline(OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(CreateSolidFillVertices(
renderer.GetTessellator(),
GetCover()
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: GetPath(),
host_buffer));
auto allocator = renderer.GetContext()->GetResourceAllocator();
auto geometry_result = GetGeometry()->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.BindVertices(geometry_result.vertex_buffer);
cmd.primitive_type = geometry_result.type;
VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info));
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(cmd, texture_,

View File

@@ -53,7 +53,8 @@ bool VerticesContents::Render(const ContentContext& renderer,
using VS = GeometryColorPipeline::VertexShader;
auto geometry_result = geometry_->GetPositionColorBuffer(
allocator, host_buffer, color_, blend_mode_);
allocator, host_buffer, renderer.GetTessellator(), color_,
blend_mode_);
cmd.pipeline = renderer.GetGeometryColorPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.primitive_type = geometry_result.type;
@@ -69,8 +70,9 @@ bool VerticesContents::Render(const ContentContext& renderer,
case GeometryVertexType::kPosition: {
using VS = GeometryPositionPipeline::VertexShader;
auto geometry_result =
geometry_->GetPositionBuffer(allocator, host_buffer);
auto geometry_result = geometry_->GetPositionBuffer(
allocator, host_buffer, renderer.GetTessellator(),
pass.GetRenderTargetSize());
cmd.pipeline = renderer.GetGeometryPositionPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.primitive_type = geometry_result.type;

View File

@@ -294,8 +294,8 @@ TEST_P(EntityTest, StrokeCapAndJoinTest) {
auto coverage = entity.GetCoverage();
if (coverage.has_value()) {
auto bounds_contents = std::make_unique<SolidColorContents>();
bounds_contents->SetPath(
PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
bounds_contents->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
Entity bounds_entity;
bounds_entity.SetContents(std::move(bounds_contents));
@@ -949,7 +949,8 @@ TEST_P(EntityTest, GaussianBlurFilter) {
} else {
auto fill = std::make_shared<SolidColorContents>();
fill->SetColor(input_color);
fill->SetPath(PathBuilder{}.AddRect(input_rect).TakePath());
fill->SetGeometry(
Geometry::MakePath(PathBuilder{}.AddRect(input_rect).TakePath()));
input = fill;
input_size = input_rect.size;
@@ -1185,8 +1186,8 @@ TEST_P(EntityTest, SolidStrokeCoverageIsCorrect) {
TEST_P(EntityTest, BorderMaskBlurCoverageIsCorrect) {
auto fill = std::make_shared<SolidColorContents>();
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
fill->SetColor(Color::CornflowerBlue());
auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
FilterInput::Make(fill), Radius{3}, Radius{4});
@@ -1417,7 +1418,8 @@ TEST_P(EntityTest, SolidFillCoverageIsCorrect) {
auto fill = std::make_shared<SolidColorContents>();
fill->SetColor(Color::CornflowerBlue());
auto expected = Rect::MakeLTRB(100, 110, 200, 220);
fill->SetPath(PathBuilder{}.AddRect(expected).TakePath());
fill->SetGeometry(
Geometry::MakePath(PathBuilder{}.AddRect(expected).TakePath()));
auto coverage = fill->GetCoverage({});
ASSERT_TRUE(coverage.has_value());
@@ -1428,8 +1430,8 @@ TEST_P(EntityTest, SolidFillCoverageIsCorrect) {
{
auto fill = std::make_shared<SolidColorContents>();
fill->SetColor(Color::CornflowerBlue());
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
Entity entity;
entity.SetTransformation(Matrix::MakeTranslation(Vector2(4, 5)));
@@ -1445,8 +1447,8 @@ TEST_P(EntityTest, SolidFillCoverageIsCorrect) {
{
auto fill = std::make_shared<SolidColorContents>();
fill->SetColor(Color::WhiteTransparent());
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
auto coverage = fill->GetCoverage({});
ASSERT_FALSE(coverage.has_value());
@@ -1467,8 +1469,8 @@ TEST_P(EntityTest, SolidFillShouldRenderIsCorrect) {
{
auto fill = std::make_shared<SolidColorContents>();
fill->SetColor(Color::CornflowerBlue());
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
ASSERT_FALSE(
fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
@@ -1478,7 +1480,7 @@ TEST_P(EntityTest, SolidFillShouldRenderIsCorrect) {
{
auto fill = std::make_shared<SolidColorContents>();
fill->SetColor(Color::CornflowerBlue());
fill->SetCover(true);
fill->SetGeometry(Geometry::MakeCover());
ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
ASSERT_TRUE(
fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
@@ -1492,8 +1494,8 @@ TEST_P(EntityTest, ClipContentsShouldRenderIsCorrect) {
{
auto clip = std::make_shared<ClipContents>();
ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
clip->SetPath(
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath());
clip->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
ASSERT_TRUE(
clip->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
@@ -1552,8 +1554,8 @@ TEST_P(EntityTest, RRectShadowTest) {
auto coverage = entity.GetCoverage();
if (show_coverage && coverage.has_value()) {
auto bounds_contents = std::make_unique<SolidColorContents>();
bounds_contents->SetPath(
PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath());
bounds_contents->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
bounds_contents->SetColor(coverage_color.Premultiply());
Entity bounds_entity;
bounds_entity.SetContents(std::move(bounds_contents));
@@ -1568,8 +1570,8 @@ TEST_P(EntityTest, RRectShadowTest) {
TEST_P(EntityTest, ColorMatrixFilterCoverageIsCorrect) {
// Set up a simple color background.
auto fill = std::make_shared<SolidColorContents>();
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
fill->SetColor(Color::Coral());
// Set the color matrix filter.
@@ -1662,8 +1664,8 @@ TEST_P(EntityTest, ColorMatrixFilterEditable) {
TEST_P(EntityTest, LinearToSrgbFilterCoverageIsCorrect) {
// Set up a simple color background.
auto fill = std::make_shared<SolidColorContents>();
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
fill->SetColor(Color::MintCream());
auto filter = FilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
@@ -1713,8 +1715,8 @@ TEST_P(EntityTest, LinearToSrgbFilter) {
TEST_P(EntityTest, SrgbToLinearFilterCoverageIsCorrect) {
// Set up a simple color background.
auto fill = std::make_shared<SolidColorContents>();
fill->SetPath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath());
fill->SetGeometry(Geometry::MakePath(
PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
fill->SetColor(Color::DeepPink());
auto filter = FilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));

View File

@@ -5,7 +5,9 @@
#include "impeller/entity/geometry.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/position_color.vert.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/device_buffer.h"
#include "impeller/tessellator/tessellator.h"
namespace impeller {
@@ -18,6 +20,16 @@ std::unique_ptr<Geometry> Geometry::MakeVertices(Vertices vertices) {
return std::make_unique<VerticesGeometry>(std::move(vertices));
}
std::unique_ptr<Geometry> Geometry::MakePath(Path path) {
return std::make_unique<PathGeometry>(std::move(path));
}
std::unique_ptr<Geometry> Geometry::MakeCover() {
return std::make_unique<CoverGeometry>();
}
/////// Vertices Geometry ///////
VerticesGeometry::VerticesGeometry(Vertices vertices)
: vertices_(std::move(vertices)) {}
@@ -34,7 +46,9 @@ static PrimitiveType GetPrimitiveType(const Vertices& vertices) {
GeometryResult VerticesGeometry::GetPositionBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer) {
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
if (!vertices_.IsValid()) {
return {};
}
@@ -80,6 +94,7 @@ GeometryResult VerticesGeometry::GetPositionBuffer(
GeometryResult VerticesGeometry::GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) {
using VS = GeometryColorPipeline::VertexShader;
@@ -140,6 +155,7 @@ GeometryResult VerticesGeometry::GetPositionColorBuffer(
GeometryResult VerticesGeometry::GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
// TODO(jonahwilliams): support texture coordinates in vertices.
return {};
@@ -156,4 +172,120 @@ std::optional<Rect> VerticesGeometry::GetCoverage(Matrix transform) {
return vertices_.GetTransformedBoundingBox(transform);
}
/////// Path Geometry ///////
PathGeometry::PathGeometry(Path path) : path_(std::move(path)) {}
PathGeometry::~PathGeometry() = default;
GeometryResult PathGeometry::GetPositionBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
VertexBuffer vertex_buffer;
auto tesselation_result = tessellator->TessellateBuilder(
path_.GetFillType(), path_.CreatePolyline(),
[&vertex_buffer, &host_buffer](
const float* vertices, size_t vertices_count, const uint16_t* indices,
size_t indices_count) {
vertex_buffer.vertex_buffer = host_buffer.Emplace(
vertices, vertices_count * sizeof(float), alignof(float));
vertex_buffer.index_buffer = host_buffer.Emplace(
indices, indices_count * sizeof(uint16_t), alignof(uint16_t));
vertex_buffer.index_count = indices_count;
vertex_buffer.index_type = IndexType::k16bit;
return true;
});
if (tesselation_result != Tessellator::Result::kSuccess) {
return {};
}
return GeometryResult{
.type = PrimitiveType::kTriangle,
.vertex_buffer = vertex_buffer,
.prevent_overdraw = false,
};
}
GeometryResult PathGeometry::GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) {
// TODO(jonahwilliams): support per-color vertex in path geometry.
return {};
}
GeometryResult PathGeometry::GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
// TODO(jonahwilliams): support texture coordinates in path geometry.
return {};
}
GeometryVertexType PathGeometry::GetVertexType() {
return GeometryVertexType::kPosition;
}
std::optional<Rect> PathGeometry::GetCoverage(Matrix transform) {
return path_.GetTransformedBoundingBox(transform);
}
/////// Cover Geometry ///////
CoverGeometry::CoverGeometry() = default;
CoverGeometry::~CoverGeometry() = default;
GeometryResult CoverGeometry::GetPositionBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
auto rect = Rect(Size(render_target_size));
constexpr uint16_t kRectIndicies[4] = {0, 1, 2, 3};
return GeometryResult{
.type = PrimitiveType::kTriangleStrip,
.vertex_buffer = {.vertex_buffer = host_buffer.Emplace(
rect.GetPoints().data(), 8 * sizeof(float),
alignof(float)),
.index_buffer = host_buffer.Emplace(
kRectIndicies, 4 * sizeof(uint16_t),
alignof(uint16_t)),
.index_count = 4,
.index_type = IndexType::k16bit},
.prevent_overdraw = false,
};
}
GeometryResult CoverGeometry::GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) {
// TODO(jonahwilliams): support per-color vertex in cover geometry.
return {};
}
GeometryResult CoverGeometry::GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) {
// TODO(jonahwilliams): support texture coordinates in cover geometry.
return {};
}
GeometryVertexType CoverGeometry::GetVertexType() {
return GeometryVertexType::kPosition;
}
std::optional<Rect> CoverGeometry::GetCoverage(Matrix transform) {
return Rect::MakeMaximum();
}
} // namespace impeller

View File

@@ -13,6 +13,8 @@
namespace impeller {
class Tessellator;
struct GeometryResult {
PrimitiveType type;
VertexBuffer vertex_buffer;
@@ -33,19 +35,27 @@ class Geometry {
static std::unique_ptr<Geometry> MakeVertices(Vertices vertices);
static std::unique_ptr<Geometry> MakePath(Path path);
static std::unique_ptr<Geometry> MakeCover();
virtual GeometryResult GetPositionBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer) = 0;
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) = 0;
virtual GeometryResult GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) = 0;
virtual GeometryResult GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) = 0;
virtual GeometryVertexType GetVertexType() = 0;
@@ -53,6 +63,7 @@ class Geometry {
virtual std::optional<Rect> GetCoverage(Matrix transform) = 0;
};
/// @brief A geometry that is created from a vertices object.
class VerticesGeometry : public Geometry {
public:
VerticesGeometry(Vertices vertices);
@@ -62,12 +73,15 @@ class VerticesGeometry : public Geometry {
private:
// |Geometry|
GeometryResult GetPositionBuffer(std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer) override;
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) override;
// |Geometry|
GeometryResult GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) override;
@@ -75,6 +89,7 @@ class VerticesGeometry : public Geometry {
GeometryResult GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) override;
// |Geometry|
@@ -88,4 +103,83 @@ class VerticesGeometry : public Geometry {
FML_DISALLOW_COPY_AND_ASSIGN(VerticesGeometry);
};
/// @brief A geometry that is created from a path object.
class PathGeometry : public Geometry {
public:
PathGeometry(Path path);
~PathGeometry();
private:
// |Geometry|
GeometryResult GetPositionBuffer(std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) override;
// |Geometry|
GeometryResult GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) override;
// |Geometry|
GeometryResult GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) override;
// |Geometry|
GeometryVertexType GetVertexType() override;
// |Geometry|
std::optional<Rect> GetCoverage(Matrix transform) override;
Path path_;
FML_DISALLOW_COPY_AND_ASSIGN(PathGeometry);
};
/// @brief A geometry that implements "drawPaint" like behavior by covering
/// the entire render pass area.
class CoverGeometry : public Geometry {
public:
CoverGeometry();
~CoverGeometry();
private:
// |Geometry|
GeometryResult GetPositionBuffer(std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) override;
// |Geometry|
GeometryResult GetPositionColorBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
Color paint_color,
BlendMode blend_mode) override;
// |Geometry|
GeometryResult GetPositionUVBuffer(
std::shared_ptr<Allocator> device_allocator,
HostBuffer& host_buffer,
std::shared_ptr<Tessellator> tessellator,
ISize render_target_size) override;
// |Geometry|
GeometryVertexType GetVertexType() override;
// |Geometry|
std::optional<Rect> GetCoverage(Matrix transform) override;
FML_DISALLOW_COPY_AND_ASSIGN(CoverGeometry);
};
} // namespace impeller

View File

@@ -73,6 +73,13 @@ struct TRect {
return TRect::MakeLTRB(left, top, right, bottom);
}
constexpr static TRect MakeMaximum() {
return TRect::MakeLTRB(-std::numeric_limits<Scalar>::infinity(),
-std::numeric_limits<Scalar>::infinity(),
std::numeric_limits<Scalar>::infinity(),
std::numeric_limits<Scalar>::infinity());
}
template <class U>
constexpr explicit TRect(const TRect<U>& other)
: origin(static_cast<TPoint<Type>>(other.origin)),