Skip to content

Commit

Permalink
Rendering of continuous strokes.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored and dnfield committed Apr 27, 2022
1 parent 41ed619 commit ac10b79
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 7 deletions.
12 changes: 12 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ TEST_F(AiksTest, CanRenderStrokes) {
Paint paint;
paint.color = Color::Red();
paint.stroke_width = 20.0;
paint.style = Paint::Style::kStroke;
canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).CreatePath(),
paint);
// ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_F(AiksTest, CanRenderCurvedStrokes) {
Canvas canvas;
Paint paint;
paint.color = Color::Blue();
paint.stroke_width = 25.0;
paint.style = Paint::Style::kStroke;
canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).CreatePath(), paint);
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
Expand Down
2 changes: 2 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ impeller_shaders("entity_shaders") {
"shaders/gradient_fill.vert",
"shaders/solid_fill.frag",
"shaders/solid_fill.vert",
"shaders/solid_stroke.frag",
"shaders/solid_stroke.vert",
"shaders/texture_fill.frag",
"shaders/texture_fill.vert",
]
Expand Down
9 changes: 9 additions & 0 deletions impeller/entity/content_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ContentRenderer::ContentRenderer(std::shared_ptr<Context> context)
gradient_fill_pipeline_ = std::make_unique<GradientFillPipeline>(*context_);
solid_fill_pipeline_ = std::make_unique<SolidFillPipeline>(*context_);
texture_pipeline_ = std::make_unique<TexturePipeline>(*context_);
solid_stroke_pipeline_ = std::make_unique<SolidStrokePipeline>(*context_);

is_valid_ = true;
}
Expand Down Expand Up @@ -52,4 +53,12 @@ std::shared_ptr<Pipeline> ContentRenderer::GetTexturePipeline() const {
return texture_pipeline_->WaitAndGet();
}

std::shared_ptr<Pipeline> ContentRenderer::GetSolidStrokePipeline() const {
if (!IsValid()) {
return nullptr;
}

return solid_stroke_pipeline_->WaitAndGet();
}

} // namespace impeller
7 changes: 7 additions & 0 deletions impeller/entity/content_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "flutter/impeller/entity/gradient_fill.vert.h"
#include "flutter/impeller/entity/solid_fill.frag.h"
#include "flutter/impeller/entity/solid_fill.vert.h"
#include "flutter/impeller/entity/solid_stroke.frag.h"
#include "flutter/impeller/entity/solid_stroke.vert.h"
#include "flutter/impeller/entity/texture_fill.frag.h"
#include "flutter/impeller/entity/texture_fill.vert.h"
#include "impeller/renderer/pipeline.h"
Expand All @@ -23,6 +25,8 @@ using SolidFillPipeline =
PipelineT<SolidFillVertexShader, SolidFillFragmentShader>;
using TexturePipeline =
PipelineT<TextureFillVertexShader, TextureFillFragmentShader>;
using SolidStrokePipeline =
PipelineT<SolidStrokeVertexShader, SolidStrokeFragmentShader>;

class ContentRenderer {
public:
Expand All @@ -38,13 +42,16 @@ class ContentRenderer {

std::shared_ptr<Pipeline> GetTexturePipeline() const;

std::shared_ptr<Pipeline> GetSolidStrokePipeline() const;

std::shared_ptr<Context> GetContext() const;

private:
std::shared_ptr<Context> context_;
std::unique_ptr<GradientFillPipeline> gradient_fill_pipeline_;
std::unique_ptr<SolidFillPipeline> solid_fill_pipeline_;
std::unique_ptr<TexturePipeline> texture_pipeline_;
std::unique_ptr<SolidStrokePipeline> solid_stroke_pipeline_;
bool is_valid_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(ContentRenderer);
Expand Down
68 changes: 64 additions & 4 deletions impeller/entity/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "impeller/entity/content_renderer.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/vector.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/renderer/surface.h"
Expand Down Expand Up @@ -236,13 +237,11 @@ bool TextureContents::Render(const ContentRenderer& renderer,
frame_info.mvp =
Matrix::MakeOrthographic(surface.GetSize()) * entity.GetTransformation();

auto frame_info_view = host_buffer.EmplaceUniform(frame_info);

Command cmd;
cmd.label = "TextureFill";
cmd.pipeline = renderer.GetTexturePipeline();
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
VS::BindFrameInfo(cmd, frame_info_view);
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
FS::BindTextureSampler(
cmd, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler({}));
Expand Down Expand Up @@ -275,6 +274,45 @@ const Color& SolidStrokeContents::GetColor() const {
return color_;
}

static VertexBuffer CreateSolidStrokeVertices(const Path& path,
HostBuffer& buffer) {
using VS = SolidStrokeVertexShader;

VertexBufferBuilder<VS::PerVertexData> vtx_builder;
auto polyline = path.CreatePolyline();

for (size_t i = 0, polyline_size = polyline.size(); i < polyline_size; i++) {
const auto is_last_point = i == polyline_size - 1;

const auto& p1 = polyline[i];
const auto& p2 = is_last_point ? polyline[i - 1] : polyline[i + 1];

const auto diff = p2 - p1;

const Scalar direction = is_last_point ? -1.0 : 1.0;

const auto normal =
Point{-diff.y * direction, diff.x * direction}.Normalize();

VS::PerVertexData vtx;
vtx.vertex_position = p1;

if (i == 0) {
vtx.vertex_normal = -normal;
vtx_builder.AppendVertex(vtx);
vtx.vertex_normal = normal;
vtx_builder.AppendVertex(vtx);
}

vtx.vertex_normal = normal;
vtx_builder.AppendVertex(vtx);
vtx.vertex_normal = -normal;
vtx_builder.AppendVertex(vtx);
}

return vtx_builder.CreateVertexBuffer(buffer);
}

bool SolidStrokeContents::Render(const ContentRenderer& renderer,
const Entity& entity,
const Surface& surface,
Expand All @@ -283,7 +321,29 @@ bool SolidStrokeContents::Render(const ContentRenderer& renderer,
return true;
}

return false;
using VS = SolidStrokeVertexShader;

VS::FrameInfo frame_info;
frame_info.mvp =
Matrix::MakeOrthographic(surface.GetSize()) * entity.GetTransformation();

VS::StrokeInfo stroke_info;
stroke_info.color = color_;
stroke_info.size = stroke_size_;

Command cmd;
cmd.primitive_type = PrimitiveType::kTriangleStrip;
cmd.label = "SolidStroke";
cmd.pipeline = renderer.GetSolidStrokePipeline();
cmd.BindVertices(
CreateSolidStrokeVertices(entity.GetPath(), pass.GetTransientsBuffer()));
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
VS::BindStrokeInfo(cmd,
pass.GetTransientsBuffer().EmplaceUniform(stroke_info));

pass.AddCommand(std::move(cmd));

return true;
}

void SolidStrokeContents::SetStrokeSize(Scalar size) {
Expand Down
11 changes: 11 additions & 0 deletions impeller/entity/shaders/solid_stroke.frag
Original file line number Diff line number Diff line change
@@ -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.

in vec4 stroke_color;

out vec4 frag_color;

void main() {
frag_color = stroke_color;
}
23 changes: 23 additions & 0 deletions impeller/entity/shaders/solid_stroke.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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.

uniform FrameInfo {
mat4 mvp;
} frame_info;

uniform StrokeInfo {
vec4 color;
float size;
} stroke_info;

in vec2 vertex_position;
in vec2 vertex_normal;

out vec4 stroke_color;

void main() {
vec2 offset = vertex_normal * vec2(stroke_info.size * 0.5);
gl_Position = frame_info.mvp * vec4(vertex_position + offset, 0.0, 1.0);
stroke_color = stroke_info.color;
}
5 changes: 5 additions & 0 deletions impeller/geometry/path_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ PathBuilder& PathBuilder::AddOval(const Rect& container) {
return *this;
}

PathBuilder& PathBuilder::AddLine(const Point& p1, const Point& p2) {
prototype_.AddLinearComponent(p1, p2);
return *this;
}

const Path& PathBuilder::GetCurrentPath() const {
return prototype_;
}
Expand Down
2 changes: 2 additions & 0 deletions impeller/geometry/path_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class PathBuilder {

PathBuilder& AddOval(const Rect& rect);

PathBuilder& AddLine(const Point& p1, const Point& p2);

struct RoundingRadii {
Scalar topLeft = 0.0;
Scalar bottomLeft = 0.0;
Expand Down
12 changes: 12 additions & 0 deletions impeller/geometry/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,18 @@ struct TPoint {
constexpr Type GetDistance(const TPoint& p) const {
return sqrt(GetDistanceSquared(p));
}

constexpr Type GetLengthSquared() const { return GetDistanceSquared({}); }

constexpr Type GetLength() const { return GetDistance({}); }

constexpr TPoint Normalize() const {
const auto length = GetLength();
if (length == 0) {
return {};
}
return {x / length, y / length};
}
};

using Point = TPoint<Scalar>;
Expand Down
11 changes: 10 additions & 1 deletion impeller/renderer/backend/metal/vertex_descriptor_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <Metal/Metal.h>

#include <set>

#include "flutter/fml/macros.h"
#include "impeller/renderer/backend/metal/backend_cast.h"
#include "impeller/renderer/vertex_descriptor.h"
Expand All @@ -28,8 +30,15 @@ class VertexDescriptorMTL {

StageInput(size_t p_location, MTLVertexFormat p_format, size_t p_length)
: location(p_location), format(p_format), length(p_length) {}

struct Compare {
constexpr bool operator()(const StageInput& lhs,
const StageInput& rhs) const {
return lhs.location < rhs.location;
}
};
};
std::vector<StageInput> stage_inputs_;
std::set<StageInput, StageInput::Compare> stage_inputs_;

FML_DISALLOW_COPY_AND_ASSIGN(VertexDescriptorMTL);
};
Expand Down
5 changes: 3 additions & 2 deletions impeller/renderer/backend/metal/vertex_descriptor_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ static MTLVertexFormat ReadStageInputFormat(const ShaderStageIOSlot& input) {
FML_LOG(ERROR) << "Format for input " << input.name << " not supported.";
return false;
}
stage_inputs_.emplace_back(StageInput{
input.location, vertex_format, (input.bit_width * input.vec_size) / 8});

stage_inputs_.insert(StageInput{input.location, vertex_format,
(input.bit_width * input.vec_size) / 8});
}

return true;
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/shader_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct ShaderUniformSlot {

struct ShaderStageIOSlot {
// Statically allocated const string containing advisory debug description.
// This may be absent in release modes and the runtime may not use this string
// for normal operation.
const char* name;
size_t location;
size_t set;
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/vertex_buffer_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class VertexBufferBuilder {

bool HasVertices() const { return !vertices_.empty(); }

size_t GetVertexCount() const { return vertices_.size(); }

VertexBufferBuilder& AppendVertex(VertexType_ vertex) {
vertices_.emplace_back(std::move(vertex));
return *this;
Expand Down

0 comments on commit ac10b79

Please sign in to comment.