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 all 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> transforms,
std::vector<Rect> texture_coordinates,
std::vector<Color> colors,
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->SetTransforms(std::move(transforms));
contents->SetTextureCoordinates(std::move(texture_coordinates));
contents->SetTexture(atlas->GetTexture());
contents->SetSamplerDescriptor(std::move(sampler));
contents->SetBlendMode(blend_mode);
// TODO(jonahwilliams): set cull rect.

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
9 changes: 9 additions & 0 deletions impeller/aiks/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ class Canvas {
Entity::BlendMode blend_mode,
Paint paint);

void DrawAtlas(std::shared_ptr<Image> atlas,
std::vector<Matrix> transforms,
std::vector<Rect> texture_coordinates,
std::vector<Color> colors,
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), 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
137 changes: 137 additions & 0 deletions impeller/entity/contents/atlas_contents.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// 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 <optional>

#include "impeller/renderer/formats.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/renderer/vertex_buffer_builder.h"

#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/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::SetTransforms(std::vector<Matrix> transforms) {
transforms_ = transforms;
}

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 {
Rect bounding_box = {};
for (size_t i = 0; i < texture_coords_.size(); i++) {
auto matrix = transforms_[i];
auto sample_rect = texture_coords_[i];
auto bounds = Rect::MakeSize(sample_rect.size).TransformBounds(matrix);
bounding_box = bounds.Union(bounding_box);
}
return bounding_box.TransformBounds(entity.GetTransformation());
}

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 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 indices[6] = {0, 1, 2, 1, 2, 3};
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 = transforms_[i];
auto color = (colors_.size() > 0 ? colors_[i] : Color::Black());
auto transformed_points =
Rect::MakeSize(sample_rect.size).GetTransformedPoints(matrix);

for (size_t j = 0; j < 6; j++) {
VS::PerVertexData data;
data.position = transformed_points[indices[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
59 changes: 59 additions & 0 deletions impeller/entity/contents/atlas_contents.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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 SetTransforms(std::vector<Matrix> transforms);

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> transforms_;
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