Skip to content

Commit

Permalink
[Impeller] Make 'DrawPaint' support color sources (flutter#36115)
Browse files Browse the repository at this point in the history
  • Loading branch information
ColdPaleLight authored Sep 14, 2022
1 parent 685b06c commit a1f978a
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 119 deletions.
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@ 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
Expand Down
1 change: 1 addition & 0 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ std::shared_ptr<Contents> Paint::CreateContentsForEntity(Path path,
auto contents = source();
contents->SetPath(std::move(path));
contents->SetAlpha(color.alpha);
contents->SetCover(cover);
return contents;
}

Expand Down
52 changes: 52 additions & 0 deletions impeller/display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -704,5 +704,57 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(DisplayListTest, CanDrawPaintWithColorSource) {
const flutter::DlColor colors[2] = {
flutter::DlColor(0xFFF44336),
flutter::DlColor(0xFF2196F3),
};
const float stops[2] = {0.0, 1.0};
flutter::DlPaint paint;
flutter::DisplayListBuilder builder;
auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
builder.save();
builder.translate(100, 100);
builder.clipRect(clip_bounds, SkClipOp::kIntersect, false);
auto linear =
flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
stops, flutter::DlTileMode::kRepeat);
paint.setColorSource(linear);
builder.drawPaint(paint);
builder.restore();

builder.save();
builder.translate(500, 100);
builder.clipRect(clip_bounds, SkClipOp::kIntersect, false);
auto radial = flutter::DlColorSource::MakeRadial(
{100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
paint.setColorSource(radial);
builder.drawPaint(paint);
builder.restore();

builder.save();
builder.translate(100, 500);
builder.clipRect(clip_bounds, SkClipOp::kIntersect, false);
auto sweep =
flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
stops, flutter::DlTileMode::kRepeat);
paint.setColorSource(sweep);
builder.drawPaint(paint);
builder.restore();

builder.save();
builder.translate(500, 500);
builder.clipRect(clip_bounds, SkClipOp::kIntersect, false);
auto texture = CreateTextureForFixture("table_mountain_nx.png");
auto image = std::make_shared<flutter::DlImageColorSource>(
DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
flutter::DlTileMode::kRepeat);
paint.setColorSource(image);
builder.drawPaint(paint);
builder.restore();

ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

} // namespace testing
} // namespace impeller
2 changes: 2 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ 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",
Expand Down
4 changes: 2 additions & 2 deletions impeller/entity/contents/clip_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +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_color_contents.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"
Expand Down Expand Up @@ -119,7 +119,7 @@ bool ClipContents::Render(const ContentContext& renderer,
}

cmd.pipeline = renderer.GetClipPipeline(options);
cmd.BindVertices(SolidColorContents::CreateSolidFillVertices(
cmd.BindVertices(CreateSolidFillVertices<VS::PerVertexData>(
path_, pass.GetTransientsBuffer()));

info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
Expand Down
17 changes: 17 additions & 0 deletions impeller/entity/contents/color_source_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,26 @@ 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());
};

bool ColorSourceContents::ShouldRender(
const Entity& entity,
const std::optional<Rect>& stencil_coverage) const {
if (!stencil_coverage.has_value()) {
return false;
}
return cover_ || Contents::ShouldRender(entity, stencil_coverage);
}

} // namespace impeller
9 changes: 9 additions & 0 deletions impeller/entity/contents/color_source_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,29 @@ class ColorSourceContents : public Contents {

void SetAlpha(Scalar alpha);

void SetCover(bool cover);

// |Contents|
std::optional<Rect> GetCoverage(const Entity& entity) const override;

// |Contents|
bool ShouldRender(const Entity& entity,
const std::optional<Rect>& stencil_coverage) const override;

protected:
const Path& GetPath() const;

const Matrix& GetInverseMatrix() const;

Scalar GetAlpha() const;

bool GetCover() const;

private:
Path path_;
Matrix inverse_matrix_;
Scalar alpha_ = 1.0;
bool cover_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(ColorSourceContents);
};
Expand Down
28 changes: 7 additions & 21 deletions impeller/entity/contents/linear_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
#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"
#include "impeller/tessellator/tessellator.h"

namespace impeller {

Expand Down Expand Up @@ -50,24 +51,6 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
using VS = LinearGradientFillPipeline::VertexShader;
using FS = LinearGradientFillPipeline::FragmentShader;

auto vertices_builder = VertexBufferBuilder<VS::PerVertexData>();
{
auto result = Tessellator{}.Tessellate(GetPath().GetFillType(),
GetPath().CreatePolyline(),
[&vertices_builder](Point point) {
VS::PerVertexData vtx;
vtx.position = point;
vertices_builder.AppendVertex(vtx);
});

if (result == Tessellator::Result::kInputError) {
return true;
}
if (result == Tessellator::Result::kTessellationError) {
return false;
}
}

auto gradient_texture =
CreateGradientTexture(colors_, stops_, renderer.GetContext());
if (gradient_texture == nullptr) {
Expand All @@ -92,8 +75,11 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
cmd.pipeline = renderer.GetLinearGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(
vertices_builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
cmd.BindVertices(CreateSolidFillVertices<VS::PerVertexData>(
GetCover()
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: GetPath(),
pass.GetTransientsBuffer()));
cmd.primitive_type = PrimitiveType::kTriangle;
FS::BindGradientInfo(
cmd, pass.GetTransientsBuffer().EmplaceUniform(gradient_info));
Expand Down
27 changes: 7 additions & 20 deletions impeller/entity/contents/radial_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
#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"
#include "impeller/tessellator/tessellator.h"

namespace impeller {

Expand Down Expand Up @@ -48,23 +49,6 @@ bool RadialGradientContents::Render(const ContentContext& renderer,
RenderPass& pass) const {
using VS = RadialGradientFillPipeline::VertexShader;
using FS = RadialGradientFillPipeline::FragmentShader;
auto vertices_builder = VertexBufferBuilder<VS::PerVertexData>();
{
auto result = Tessellator{}.Tessellate(GetPath().GetFillType(),
GetPath().CreatePolyline(),
[&vertices_builder](Point point) {
VS::PerVertexData vtx;
vtx.position = point;
vertices_builder.AppendVertex(vtx);
});

if (result == Tessellator::Result::kInputError) {
return true;
}
if (result == Tessellator::Result::kTessellationError) {
return false;
}
}

auto gradient_texture =
CreateGradientTexture(colors_, stops_, renderer.GetContext());
Expand All @@ -90,8 +74,11 @@ bool RadialGradientContents::Render(const ContentContext& renderer,
cmd.pipeline = renderer.GetRadialGradientFillPipeline(
OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(
vertices_builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
cmd.BindVertices(CreateSolidFillVertices<VS::PerVertexData>(
GetCover()
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: GetPath(),
pass.GetTransientsBuffer()));
cmd.primitive_type = PrimitiveType::kTriangle;
FS::BindGradientInfo(
cmd, pass.GetTransientsBuffer().EmplaceUniform(gradient_info));
Expand Down
20 changes: 2 additions & 18 deletions impeller/entity/contents/solid_color_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
#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"
#include "impeller/tessellator/tessellator.h"

namespace impeller {

Expand Down Expand Up @@ -50,22 +50,6 @@ bool SolidColorContents::ShouldRender(
return cover_ || Contents::ShouldRender(entity, stencil_coverage);
}

VertexBuffer SolidColorContents::CreateSolidFillVertices(const Path& path,
HostBuffer& buffer) {
using VS = SolidFillPipeline::VertexShader;

VertexBufferBuilder<VS::PerVertexData> vtx_builder;

auto tesselation_result = Tessellator{}.Tessellate(
path.GetFillType(), path.CreatePolyline(),
[&vtx_builder](auto point) { vtx_builder.AppendVertex({point}); });
if (tesselation_result != Tessellator::Result::kSuccess) {
return {};
}

return vtx_builder.CreateVertexBuffer(buffer);
}

bool SolidColorContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
Expand All @@ -78,7 +62,7 @@ bool SolidColorContents::Render(const ContentContext& renderer,
renderer.GetSolidFillPipeline(OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();

cmd.BindVertices(CreateSolidFillVertices(
cmd.BindVertices(CreateSolidFillVertices<VS::PerVertexData>(
cover_
? PathBuilder{}.AddRect(Size(pass.GetRenderTargetSize())).TakePath()
: path_,
Expand Down
3 changes: 0 additions & 3 deletions impeller/entity/contents/solid_color_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ class SolidColorContents final : public Contents {

static std::unique_ptr<SolidColorContents> Make(Path path, Color color);

static VertexBuffer CreateSolidFillVertices(const Path& path,
HostBuffer& buffer);

void SetPath(Path path);

void SetCover(bool cover);
Expand Down
11 changes: 11 additions & 0 deletions impeller/entity/contents/solid_fill_utils.cc
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.

#include "impeller/entity/contents/solid_fill_utils.h"

namespace impeller {

//

} // namespace impeller
26 changes: 26 additions & 0 deletions impeller/entity/contents/solid_fill_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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_builder.h"
#include "impeller/tessellator/tessellator.h"

namespace impeller {

template <typename PerVertexData>
VertexBuffer CreateSolidFillVertices(const Path& path, HostBuffer& buffer) {
VertexBufferBuilder<PerVertexData> vtx_builder;

auto tesselation_result = Tessellator{}.Tessellate(
path.GetFillType(), path.CreatePolyline(),
[&vtx_builder](auto point) { vtx_builder.AppendVertex({point}); });
if (tesselation_result != Tessellator::Result::kSuccess) {
return {};
}

return vtx_builder.CreateVertexBuffer(buffer);
}

} // namespace impeller
Loading

0 comments on commit a1f978a

Please sign in to comment.