Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[impeller] drawAtlas #35009

Merged
merged 8 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ FILE: ../../../flutter/impeller/docs/assets/xcode_frame_capture/image6.png
FILE: ../../../flutter/impeller/docs/assets/xcode_frame_capture/image7.png
FILE: ../../../flutter/impeller/docs/assets/xcode_frame_capture/image8.png
FILE: ../../../flutter/impeller/docs/assets/xcode_frame_capture/image9.png
FILE: ../../../flutter/impeller/entity/contents/atlas_contents.cc
FILE: ../../../flutter/impeller/entity/contents/atlas_contents.h
FILE: ../../../flutter/impeller/entity/contents/clip_contents.cc
FILE: ../../../flutter/impeller/entity/contents/clip_contents.h
FILE: ../../../flutter/impeller/entity/contents/content_context.cc
Expand Down Expand Up @@ -590,6 +592,8 @@ FILE: ../../../flutter/impeller/entity/entity_playground.h
FILE: ../../../flutter/impeller/entity/entity_unittests.cc
FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
FILE: ../../../flutter/impeller/entity/inline_pass_context.h
FILE: ../../../flutter/impeller/entity/shaders/atlas_fill.frag
FILE: ../../../flutter/impeller/entity/shaders/atlas_fill.vert
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag
Expand Down
36 changes: 36 additions & 0 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "flutter/fml/logging.h"
#include "impeller/aiks/paint_pass_delegate.h"
#include "impeller/entity/contents/atlas_contents.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/text_contents.h"
#include "impeller/entity/contents/texture_contents.h"
Expand Down Expand Up @@ -321,4 +322,39 @@ void Canvas::DrawVertices(Vertices vertices,
GetCurrentPass().AddEntity(std::move(entity));
}

void Canvas::DrawAtlas(std::shared_ptr<Image> atlas,
std::vector<Matrix> xform,
std::vector<Rect> tex,
std::vector<Color> colors,
int count,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this count param is unused here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Although that might just be because it's WIP)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, unneeded since I'm using std::vector here

Entity::BlendMode blend_mode,
SamplerDescriptor sampler,
std::optional<Rect> cull_rect,
Paint paint) {
if (!atlas) {
return;
}
auto size = atlas->GetSize();

if (size.IsEmpty()) {
return;
}

std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
contents->SetColors(std::move(colors));
contents->SetXForm(std::move(xform));
contents->SetTextureCoordinates(std::move(tex));
contents->SetTexture(atlas->GetTexture());
contents->SetSamplerDescriptor(std::move(sampler));
contents->SetBlendMode(blend_mode);

Entity entity;
entity.SetTransformation(GetCurrentTransformation());
entity.SetStencilDepth(GetStencilDepth());
entity.SetBlendMode(paint.blend_mode);
entity.SetContents(paint.WithFilters(contents, false));

GetCurrentPass().AddEntity(std::move(entity));
}

} // namespace impeller
10 changes: 10 additions & 0 deletions impeller/aiks/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ class Canvas {
Entity::BlendMode blend_mode,
Paint paint);

void DrawAtlas(std::shared_ptr<Image> atlas,
std::vector<Matrix> xform,
std::vector<Rect> tex,
std::vector<Color> colors,
int count,
Entity::BlendMode blend_mode,
SamplerDescriptor sampler,
std::optional<Rect> cull_rect,
Paint paint);

Picture EndRecordingAsPicture();

private:
Expand Down
42 changes: 40 additions & 2 deletions impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,34 @@ static Color ToColor(const SkColor& color) {
};
}

static std::vector<Color> ToColors(const flutter::DlColor colors[], int count) {
auto result = std::vector<Color>();
if (colors == nullptr) {
return result;
}
for (int i = 0; i < count; i++) {
result.push_back(ToColor(colors[i]));
}
return result;
}

static std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count) {
auto result = std::vector<Matrix>();
for (int i = 0; i < count; i++) {
auto form = xform[i];
// clang-format off
auto matrix = Matrix{
form.fSCos, form.fSSin, 0, 0,
-form.fSSin, form.fSCos, 0, 0,
0, 0, 1, 0,
form.fTx, form.fTy, 0, 1
};
// clang-format on
result.push_back(matrix);
}
return result;
}

// |flutter::Dispatcher|
void DisplayListDispatcher::setColorSource(
const flutter::DlColorSource* source) {
Expand Down Expand Up @@ -392,6 +420,14 @@ static std::optional<Rect> ToRect(const SkRect* rect) {
return Rect::MakeLTRB(rect->fLeft, rect->fTop, rect->fRight, rect->fBottom);
}

static std::vector<Rect> ToRects(const SkRect tex[], int count) {
auto result = std::vector<Rect>();
for (int i = 0; i < count; i++) {
result.push_back(ToRect(&tex[i]).value());
}
return result;
}

// |flutter::Dispatcher|
void DisplayListDispatcher::saveLayer(const SkRect* bounds,
const flutter::SaveLayerOptions options,
Expand Down Expand Up @@ -838,8 +874,10 @@ void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
flutter::DlImageSampling sampling,
const SkRect* cull_rect,
Copy link
Member

@bdero bdero Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to incorporate this cull rect at some point, but we can do this as follow-up work. It can probably be done by either surrounding DrawAtlas with DrawClip/Restore calls or doing clipping tricks while building the draw call + coverage itself.
May be worth inserting a TODO nearby.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a todo is aiks canvas.

bool render_with_attributes) {
// Needs https://github.com/flutter/flutter/issues/95434
UNIMPLEMENTED;
canvas_.DrawAtlas(std::make_shared<Image>(atlas->impeller_texture()),
ToRSXForms(xform, count), ToRects(tex, count),
ToColors(colors, count), count, ToBlendMode(mode),
ToSamplerDescriptor(sampling), ToRect(cull_rect), paint_);
}

// |flutter::Dispatcher|
Expand Down
4 changes: 4 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ impeller_shaders("entity_shaders") {
name = "entity"

shaders = [
"shaders/atlas_fill.frag",
"shaders/atlas_fill.vert",
"shaders/blending/advanced_blend.vert",
"shaders/blending/advanced_blend_color.frag",
"shaders/blending/advanced_blend_colorburn.frag",
Expand Down Expand Up @@ -49,6 +51,8 @@ impeller_shaders("entity_shaders") {

impeller_component("entity") {
sources = [
"contents/atlas_contents.cc",
"contents/atlas_contents.h",
"contents/clip_contents.cc",
"contents/clip_contents.h",
"contents/content_context.cc",
Expand Down
145 changes: 145 additions & 0 deletions impeller/entity/contents/atlas_contents.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// 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 <iostream>
#include <optional>
#include "impeller/geometry/path_builder.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Add space between std and impeller headers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

#include "impeller/renderer/formats.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/renderer/vertex_buffer_builder.h"
#include "linear_gradient_contents.h"
Copy link
Member

@bdero bdero Aug 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unintended import?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up imports


#include "impeller/entity/atlas_fill.frag.h"
#include "impeller/entity/atlas_fill.vert.h"
#include "impeller/entity/contents/atlas_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/renderer/render_pass.h"

namespace impeller {

AtlasContents::AtlasContents() = default;

AtlasContents::~AtlasContents() = default;

void AtlasContents::SetTexture(std::shared_ptr<Texture> texture) {
texture_ = std::move(texture);
}

std::shared_ptr<Texture> AtlasContents::GetTexture() const {
return texture_;
}

void AtlasContents::SetXForm(std::vector<Matrix> xform) {
xform_ = xform;
}

void AtlasContents::SetTextureCoordinates(std::vector<Rect> texture_coords) {
texture_coords_ = texture_coords;
}

void AtlasContents::SetColors(std::vector<Color> colors) {
colors_ = colors;
}

void AtlasContents::SetBlendMode(Entity::BlendMode blend_mode) {
// TODO(jonahwilliams): blending of colors with texture.
blend_mode_ = blend_mode;
}

std::optional<Rect> AtlasContents::GetCoverage(const Entity& entity) const {
// TODO(jonahwilliams): compute coverage of atlas.
return std::nullopt;
}

void AtlasContents::SetSamplerDescriptor(SamplerDescriptor desc) {
sampler_descriptor_ = std::move(desc);
}

const SamplerDescriptor& AtlasContents::GetSamplerDescriptor() const {
return sampler_descriptor_;
}

bool AtlasContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
if (texture_ == nullptr) {
return true;
}

using VS = AtlasFillVertexShader;
using FS = AtlasFillFragmentShader;

const auto coverage_rect = path_.GetBoundingBox();

if (!coverage_rect.has_value()) {
return true;
}

if (coverage_rect->size.IsEmpty()) {
return true;
}

const auto texture_size = texture_->GetSize();
if (texture_size.IsEmpty()) {
return true;
}

VertexBufferBuilder<VS::PerVertexData> vertex_builder;
{
vertex_builder.Reserve(texture_coords_.size() * 6);
constexpr size_t indexes[6] = {0, 1, 2, 1, 2, 3};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: indices

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

constexpr Scalar width[6] = {0, 1, 0, 1, 0, 1};
constexpr Scalar height[6] = {0, 0, 1, 0, 1, 1};
for (size_t i = 0; i < texture_coords_.size(); i++) {
auto sample_rect = texture_coords_[i];
auto matrix = xform_[i];
auto color = (colors_.size() > 0 ? colors_[i] : Color::Black());
auto transformed_points = sample_rect.GetTransformedPoints(matrix);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since transformed_points is used as the position of the draw rect, should this be something like Rect::MakeSize(sample_rect.size).GetTransformedPoints(matrix)? It seems like the transformed rect should have origin 0 rather than the position used for sampling the atlas.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh this was it, thanks @bdero !


for (size_t j = 0; j < 6; j++) {
VS::PerVertexData data;
data.position = transformed_points[indexes[j]];
data.texture_coords =
(sample_rect.origin + Point(sample_rect.size.width * width[j],
sample_rect.size.height * height[j])) /
texture_size;
data.color = color.Premultiply();
vertex_builder.AppendVertex(data);
}
}
}

if (!vertex_builder.HasVertices()) {
return true;
}

auto& host_buffer = pass.GetTransientsBuffer();

VS::VertInfo vert_info;
vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();

FS::FragInfo frag_info;
frag_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale();
frag_info.has_color = colors_.size() > 0 ? 1.0 : 0.0;

Command cmd;
cmd.label = "DrawAtlas";
cmd.pipeline =
renderer.GetAtlasPipeline(OptionsFromPassAndEntity(pass, entity));
cmd.stencil_reference = entity.GetStencilDepth();
cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer));
VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info));
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
FS::BindTextureSampler(cmd, texture_,
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
sampler_descriptor_));
pass.AddCommand(std::move(cmd));

return true;
}

} // namespace impeller
60 changes: 60 additions & 0 deletions impeller/entity/contents/atlas_contents.h
Original file line number Diff line number Diff line change
@@ -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.

#pragma once

#include <functional>
#include <memory>
#include <vector>

#include "flutter/fml/macros.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/entity.h"
#include "impeller/renderer/sampler_descriptor.h"

namespace impeller {

class AtlasContents final : public Contents {
public:
explicit AtlasContents();

~AtlasContents() override;

void SetTexture(std::shared_ptr<Texture> texture);

std::shared_ptr<Texture> GetTexture() const;

void SetXForm(std::vector<Matrix> xform);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and everywhere else: Maybe "SetTransforms"? We've been using the term "transform" for any transformation matrices.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Here and everywhere else: Maybe call this SetTransforms? We've been using "Transform" for transformation matrices instead of Skia's "XForm" around Impeller.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


void SetBlendMode(Entity::BlendMode blend_mode);

void SetTextureCoordinates(std::vector<Rect> texture_coords);

void SetColors(std::vector<Color> colors);

void SetSamplerDescriptor(SamplerDescriptor desc);

const SamplerDescriptor& GetSamplerDescriptor() const;

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

// |Contents|
bool Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const override;

private:
std::shared_ptr<Texture> texture_;
std::vector<Rect> texture_coords_;
std::vector<Color> colors_;
std::vector<Matrix> xform_;
Path path_;
Entity::BlendMode blend_mode_;
SamplerDescriptor sampler_descriptor_ = {};

FML_DISALLOW_COPY_AND_ASSIGN(AtlasContents);
};

} // namespace impeller
1 change: 1 addition & 0 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
glyph_atlas_pipelines_[{}] =
CreateDefaultPipeline<GlyphAtlasPipeline>(*context_);
vertices_pipelines_[{}] = CreateDefaultPipeline<VerticesPipeline>(*context_);
atlas_pipelines_[{}] = CreateDefaultPipeline<AtlasPipeline>(*context_);

// Pipelines that are variants of the base pipelines with custom descriptors.
// TODO(98684): Rework this API to allow fetching the descriptor without
Expand Down
Loading