mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Avoid unnecessary pre-pass when filtering images (flutter/engine#35422)
This commit is contained in:
parent
b14d555542
commit
c033c0ed34
@ -274,8 +274,7 @@ void Canvas::DrawImageRect(std::shared_ptr<Image> image,
|
||||
return;
|
||||
}
|
||||
|
||||
auto contents = std::make_shared<TextureContents>();
|
||||
contents->SetPath(PathBuilder{}.AddRect(dest).TakePath());
|
||||
auto contents = TextureContents::MakeRect(dest);
|
||||
contents->SetTexture(image->GetTexture());
|
||||
contents->SetSourceRect(source);
|
||||
contents->SetSamplerDescriptor(std::move(sampler));
|
||||
|
||||
@ -34,9 +34,7 @@ bool PaintPassDelegate::CanCollapseIntoParentPass() {
|
||||
// |EntityPassDelgate|
|
||||
std::shared_ptr<Contents> PaintPassDelegate::CreateContentsForSubpassTarget(
|
||||
std::shared_ptr<Texture> target) {
|
||||
auto contents = std::make_shared<TextureContents>();
|
||||
contents->SetPath(
|
||||
PathBuilder{}.AddRect(Rect::MakeSize(target->GetSize())).TakePath());
|
||||
auto contents = TextureContents::MakeRect(Rect::MakeSize(target->GetSize()));
|
||||
contents->SetTexture(target);
|
||||
contents->SetSourceRect(Rect::MakeSize(target->GetSize()));
|
||||
contents->SetOpacity(paint_.color.alpha);
|
||||
|
||||
@ -152,10 +152,9 @@ bool FilterContents::Render(const ContentContext& renderer,
|
||||
|
||||
// Draw the result texture, respecting the transform and clip stack.
|
||||
|
||||
auto contents = std::make_shared<TextureContents>();
|
||||
contents->SetPath(
|
||||
PathBuilder{}.AddRect(filter_coverage.value()).GetCurrentPath());
|
||||
auto contents = TextureContents::MakeRect(filter_coverage.value());
|
||||
contents->SetTexture(snapshot.texture);
|
||||
contents->SetSamplerDescriptor(snapshot.sampler_descriptor);
|
||||
contents->SetSourceRect(Rect::MakeSize(snapshot.texture->GetSize()));
|
||||
|
||||
Entity e;
|
||||
|
||||
@ -104,6 +104,7 @@ std::optional<Snapshot> DirectionalGaussianBlurFilterContents::RenderFilter(
|
||||
if (!input_snapshot.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto maybe_input_uvs = input_snapshot->GetCoverageUVs(coverage);
|
||||
if (!maybe_input_uvs.has_value()) {
|
||||
return std::nullopt;
|
||||
@ -164,12 +165,6 @@ std::optional<Snapshot> DirectionalGaussianBlurFilterContents::RenderFilter(
|
||||
frag_info.outer_blur_factor = outer_blur_factor_;
|
||||
frag_info.texture_size = Point(input_snapshot->GetCoverage().value().size);
|
||||
|
||||
SamplerDescriptor sampler_desc;
|
||||
sampler_desc.min_filter = MinMagFilter::kLinear;
|
||||
sampler_desc.mag_filter = MinMagFilter::kLinear;
|
||||
auto sampler =
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc);
|
||||
|
||||
Command cmd;
|
||||
cmd.label = "Gaussian Blur Filter";
|
||||
auto options = OptionsFromPass(pass);
|
||||
@ -177,8 +172,14 @@ std::optional<Snapshot> DirectionalGaussianBlurFilterContents::RenderFilter(
|
||||
cmd.pipeline = renderer.GetGaussianBlurPipeline(options);
|
||||
cmd.BindVertices(vtx_buffer);
|
||||
|
||||
FS::BindTextureSampler(cmd, input_snapshot->texture, sampler);
|
||||
FS::BindAlphaMaskSampler(cmd, source_snapshot->texture, sampler);
|
||||
FS::BindTextureSampler(
|
||||
cmd, input_snapshot->texture,
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
input_snapshot->sampler_descriptor));
|
||||
FS::BindAlphaMaskSampler(
|
||||
cmd, source_snapshot->texture,
|
||||
renderer.GetContext()->GetSamplerLibrary()->GetSampler(
|
||||
source_snapshot->sampler_descriptor));
|
||||
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
|
||||
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
|
||||
|
||||
@ -191,8 +192,13 @@ std::optional<Snapshot> DirectionalGaussianBlurFilterContents::RenderFilter(
|
||||
}
|
||||
out_texture->SetLabel("DirectionalGaussianBlurFilter Texture");
|
||||
|
||||
SamplerDescriptor sampler_desc;
|
||||
sampler_desc.min_filter = MinMagFilter::kLinear;
|
||||
sampler_desc.mag_filter = MinMagFilter::kLinear;
|
||||
|
||||
return Snapshot{.texture = out_texture,
|
||||
.transform = Matrix::MakeTranslation(coverage.origin)};
|
||||
.transform = Matrix::MakeTranslation(coverage.origin),
|
||||
.sampler_descriptor = sampler_desc};
|
||||
}
|
||||
|
||||
std::optional<Rect> DirectionalGaussianBlurFilterContents::GetFilterCoverage(
|
||||
|
||||
@ -4,12 +4,14 @@
|
||||
|
||||
#include "texture_contents.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "impeller/entity/contents/content_context.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/entity/texture_fill.frag.h"
|
||||
#include "impeller/entity/texture_fill.vert.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
#include "impeller/renderer/render_pass.h"
|
||||
#include "impeller/renderer/sampler_library.h"
|
||||
#include "impeller/tessellator/tessellator.h"
|
||||
@ -20,8 +22,16 @@ TextureContents::TextureContents() = default;
|
||||
|
||||
TextureContents::~TextureContents() = default;
|
||||
|
||||
std::shared_ptr<TextureContents> TextureContents::MakeRect(Rect destination) {
|
||||
auto contents = std::make_shared<TextureContents>();
|
||||
contents->path_ = PathBuilder{}.AddRect(destination).TakePath();
|
||||
contents->is_rect_ = true;
|
||||
return contents;
|
||||
}
|
||||
|
||||
void TextureContents::SetPath(Path path) {
|
||||
path_ = std::move(path);
|
||||
is_rect_ = false;
|
||||
}
|
||||
|
||||
void TextureContents::SetTexture(std::shared_ptr<Texture> texture) {
|
||||
@ -43,6 +53,22 @@ std::optional<Rect> TextureContents::GetCoverage(const Entity& entity) const {
|
||||
return path_.GetTransformedBoundingBox(entity.GetTransformation());
|
||||
};
|
||||
|
||||
std::optional<Snapshot> TextureContents::RenderToSnapshot(
|
||||
const ContentContext& renderer,
|
||||
const Entity& entity) const {
|
||||
// Passthrough textures that have simple rectangle paths and complete source
|
||||
// rects.
|
||||
if (is_rect_ && source_rect_ == Rect::MakeSize(texture_->GetSize())) {
|
||||
auto scale =
|
||||
Vector2(path_.GetBoundingBox()->size / Size(texture_->GetSize()));
|
||||
return Snapshot{
|
||||
.texture = texture_,
|
||||
.transform = entity.GetTransformation() * Matrix::MakeScale(scale),
|
||||
.sampler_descriptor = sampler_descriptor_};
|
||||
}
|
||||
return Contents::RenderToSnapshot(renderer, entity);
|
||||
}
|
||||
|
||||
bool TextureContents::Render(const ContentContext& renderer,
|
||||
const Entity& entity,
|
||||
RenderPass& pass) const {
|
||||
|
||||
@ -23,6 +23,11 @@ class TextureContents final : public Contents {
|
||||
|
||||
~TextureContents() override;
|
||||
|
||||
/// @brief A common case factory that marks the texture contents as having a
|
||||
/// destination rectangle. In this situation, a subpass can be avoided
|
||||
/// when image filters are applied.
|
||||
static std::shared_ptr<TextureContents> MakeRect(Rect destination);
|
||||
|
||||
void SetPath(Path path);
|
||||
|
||||
void SetTexture(std::shared_ptr<Texture> texture);
|
||||
@ -42,13 +47,18 @@ class TextureContents final : public Contents {
|
||||
// |Contents|
|
||||
std::optional<Rect> GetCoverage(const Entity& entity) const override;
|
||||
|
||||
// |Contents|
|
||||
std::optional<Snapshot> RenderToSnapshot(const ContentContext& renderer,
|
||||
const Entity& entity) const override;
|
||||
|
||||
// |Contents|
|
||||
bool Render(const ContentContext& renderer,
|
||||
const Entity& entity,
|
||||
RenderPass& pass) const override;
|
||||
|
||||
public:
|
||||
private:
|
||||
Path path_;
|
||||
bool is_rect_ = false;
|
||||
|
||||
std::shared_ptr<Texture> texture_;
|
||||
SamplerDescriptor sampler_descriptor_ = {};
|
||||
|
||||
@ -161,8 +161,7 @@ bool EntityPass::Render(ContentContext& renderer,
|
||||
|
||||
{
|
||||
auto size_rect = Rect::MakeSize(offscreen_target.GetRenderTargetSize());
|
||||
auto contents = std::make_shared<TextureContents>();
|
||||
contents->SetPath(PathBuilder{}.AddRect(size_rect).TakePath());
|
||||
auto contents = TextureContents::MakeRect(size_rect);
|
||||
contents->SetTexture(offscreen_target.GetRenderTargetTexture());
|
||||
contents->SetSourceRect(size_rect);
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/geometry/matrix.h"
|
||||
#include "impeller/geometry/rect.h"
|
||||
#include "impeller/renderer/sampler_descriptor.h"
|
||||
#include "impeller/renderer/texture.h"
|
||||
|
||||
namespace impeller {
|
||||
@ -18,12 +19,14 @@ namespace impeller {
|
||||
class ContentContext;
|
||||
class Entity;
|
||||
|
||||
/// Represents a texture and its intended draw position.
|
||||
/// Represents a texture and its intended draw transform/sampler configuration.
|
||||
struct Snapshot {
|
||||
std::shared_ptr<Texture> texture;
|
||||
/// The transform that should be applied to this texture for rendering.
|
||||
Matrix transform;
|
||||
|
||||
SamplerDescriptor sampler_descriptor;
|
||||
|
||||
std::optional<Rect> GetCoverage() const;
|
||||
|
||||
/// @brief Get the transform that converts screen space coordinates to the UV
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user