-
Notifications
You must be signed in to change notification settings - Fork 6k
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
[impeller] drawAtlas #35009
Changes from 6 commits
320cb32
a3b31d6
4a69912
42792c6
d29db5f
7132185
de84926
0563130
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) { | ||
|
@@ -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, | ||
|
@@ -838,8 +874,10 @@ void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas, | |
flutter::DlImageSampling sampling, | ||
const SkRect* cull_rect, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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| | ||
|
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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Add space between std and impeller headers. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unintended import? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: indices There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Here and everywhere else: Maybe call this There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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