Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Return entities from filters instead of snapshots #39560

Merged
merged 1 commit into from
Feb 13, 2023
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
25 changes: 25 additions & 0 deletions impeller/entity/contents/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "fml/logging.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
Expand All @@ -31,6 +32,30 @@ ContentContextOptions OptionsFromPassAndEntity(const RenderPass& pass,
return opts;
}

std::optional<Entity> Contents::EntityFromSnapshot(
const std::optional<Snapshot>& snapshot,
BlendMode blend_mode,
uint32_t stencil_depth) {
if (!snapshot.has_value()) {
return std::nullopt;
}

auto texture_rect = Rect::MakeSize(snapshot->texture->GetSize());

auto contents = TextureContents::MakeRect(texture_rect);
contents->SetTexture(snapshot->texture);
contents->SetSamplerDescriptor(snapshot->sampler_descriptor);
contents->SetSourceRect(texture_rect);
contents->SetOpacity(snapshot->opacity);

Entity entity;
entity.SetBlendMode(blend_mode);
entity.SetStencilDepth(stencil_depth);
entity.SetTransformation(snapshot->transform);
entity.SetContents(contents);
return entity;
}

Contents::Contents() = default;

Contents::~Contents() = default;
Expand Down
7 changes: 7 additions & 0 deletions impeller/entity/contents/contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vector>

#include "flutter/fml/macros.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/rect.h"
#include "impeller/renderer/sampler_descriptor.h"
#include "impeller/renderer/snapshot.h"
Expand Down Expand Up @@ -40,6 +41,12 @@ class Contents {
std::optional<Rect> coverage = std::nullopt;
};

/// @brief Create an entity that renders a given snapshot.
static std::optional<Entity> EntityFromSnapshot(
const std::optional<Snapshot>& snapshot,
BlendMode blend_mode = BlendMode::kSourceOver,
uint32_t stencil_depth = 0);

virtual bool Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const = 0;
Expand Down
80 changes: 47 additions & 33 deletions impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/renderer/snapshot.h"

namespace impeller {

Expand All @@ -30,7 +31,7 @@ using PipelineProc = std::shared_ptr<Pipeline<PipelineDescriptor>> (
ContentContext::*)(ContentContextOptions) const;

template <typename TPipeline>
static std::optional<Snapshot> AdvancedBlend(
static std::optional<Entity> AdvancedBlend(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
Expand Down Expand Up @@ -67,11 +68,19 @@ static std::optional<Snapshot> AdvancedBlend(
if (!foreground_color.has_value()) {
src_snapshot = inputs[1]->GetSnapshot(renderer, entity);
if (!src_snapshot.has_value()) {
return dst_snapshot;
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
return Contents::EntityFromSnapshot(dst_snapshot, entity.GetBlendMode(),
entity.GetStencilDepth());
}
auto maybe_src_uvs = src_snapshot->GetCoverageUVs(coverage);
if (!maybe_src_uvs.has_value()) {
return dst_snapshot;
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
return Contents::EntityFromSnapshot(dst_snapshot, entity.GetBlendMode(),
entity.GetStencilDepth());
}
src_uvs = maybe_src_uvs.value();
}
Expand Down Expand Up @@ -147,17 +156,19 @@ static std::optional<Snapshot> AdvancedBlend(
}
out_texture->SetLabel("Advanced Blend Filter Texture");

return Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
// Since we absorbed the transform of the inputs and used the
// respective snapshot sampling modes when blending, pass on
// the default NN clamp sampler.
.sampler_descriptor = {},
.opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) *
alpha.value_or(1.0)};
return Contents::EntityFromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
// Since we absorbed the transform of the inputs and used the
// respective snapshot sampling modes when blending, pass on
// the default NN clamp sampler.
.sampler_descriptor = {},
.opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) *
alpha.value_or(1.0)},
entity.GetBlendMode(), entity.GetStencilDepth());
}

static std::optional<Snapshot> PipelineBlend(
static std::optional<Entity> PipelineBlend(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
Expand Down Expand Up @@ -269,28 +280,31 @@ static std::optional<Snapshot> PipelineBlend(
}
out_texture->SetLabel("Pipeline Blend Filter Texture");

return Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
// Since we absorbed the transform of the inputs and used the
// respective snapshot sampling modes when blending, pass on
// the default NN clamp sampler.
.sampler_descriptor = {},
.opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) *
alpha.value_or(1.0)};
return Contents::EntityFromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
// Since we absorbed the transform of the inputs and used the
// respective snapshot sampling modes when blending, pass on
// the default NN clamp sampler.
.sampler_descriptor = {},
.opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) *
alpha.value_or(1.0)},
entity.GetBlendMode(), entity.GetStencilDepth());
}

#define BLEND_CASE(mode) \
case BlendMode::k##mode: \
advanced_blend_proc_ = \
[](const FilterInput::Vector& inputs, const ContentContext& renderer, \
const Entity& entity, const Rect& coverage, \
std::optional<Color> fg_color, bool absorb_opacity, \
std::optional<Scalar> alpha) { \
PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \
return AdvancedBlend<BlendScreenPipeline>(inputs, renderer, entity, \
coverage, fg_color, \
absorb_opacity, p, alpha); \
}; \
#define BLEND_CASE(mode) \
case BlendMode::k##mode: \
advanced_blend_proc_ = [](const FilterInput::Vector& inputs, \
const ContentContext& renderer, \
const Entity& entity, const Rect& coverage, \
std::optional<Color> fg_color, \
bool absorb_opacity, \
std::optional<Scalar> alpha) { \
PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \
return AdvancedBlend<Blend##mode##Pipeline>(inputs, renderer, entity, \
coverage, fg_color, \
absorb_opacity, p, alpha); \
}; \
break;

void BlendFilterContents::SetBlendMode(BlendMode blend_mode) {
Expand Down Expand Up @@ -328,7 +342,7 @@ void BlendFilterContents::SetForegroundColor(std::optional<Color> color) {
foreground_color_ = color;
}

std::optional<Snapshot> BlendFilterContents::RenderFilter(
std::optional<Entity> BlendFilterContents::RenderFilter(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
Expand Down
26 changes: 13 additions & 13 deletions impeller/entity/contents/filters/blend_filter_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ namespace impeller {

class BlendFilterContents : public ColorFilterContents {
public:
using AdvancedBlendProc = std::function<std::optional<Snapshot>(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
const Rect& coverage,
std::optional<Color> foreground_color,
bool absorb_opacity,
std::optional<Scalar> alpha)>;
using AdvancedBlendProc =
std::function<std::optional<Entity>(const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
const Rect& coverage,
std::optional<Color> foreground_color,
bool absorb_opacity,
std::optional<Scalar> alpha)>;

BlendFilterContents();

Expand All @@ -32,11 +32,11 @@ class BlendFilterContents : public ColorFilterContents {

private:
// |FilterContents|
std::optional<Snapshot> RenderFilter(const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const override;
std::optional<Entity> RenderFilter(const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const override;

BlendMode blend_mode_ = BlendMode::kSourceOver;
AdvancedBlendProc advanced_blend_proc_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void BorderMaskBlurFilterContents::SetBlurStyle(BlurStyle blur_style) {
}
}

std::optional<Snapshot> BorderMaskBlurFilterContents::RenderFilter(
std::optional<Entity> BorderMaskBlurFilterContents::RenderFilter(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
Expand Down Expand Up @@ -126,9 +126,11 @@ std::optional<Snapshot> BorderMaskBlurFilterContents::RenderFilter(
}
out_texture->SetLabel("BorderMaskBlurFilter Texture");

return Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
.opacity = input_snapshot->opacity};
return Contents::EntityFromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
.opacity = input_snapshot->opacity},
entity.GetBlendMode(), entity.GetStencilDepth());
}

std::optional<Rect> BorderMaskBlurFilterContents::GetFilterCoverage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ class BorderMaskBlurFilterContents final : public FilterContents {

private:
// |FilterContents|
std::optional<Snapshot> RenderFilter(
const FilterInput::Vector& input_textures,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const override;
std::optional<Entity> RenderFilter(const FilterInput::Vector& input_textures,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const override;

Sigma sigma_x_;
Sigma sigma_y_;
Expand Down
13 changes: 7 additions & 6 deletions impeller/entity/contents/filters/color_matrix_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void ColorMatrixFilterContents::SetMatrix(const ColorMatrix& matrix) {
matrix_ = matrix;
}

std::optional<Snapshot> ColorMatrixFilterContents::RenderFilter(
std::optional<Entity> ColorMatrixFilterContents::RenderFilter(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
Expand Down Expand Up @@ -104,11 +104,12 @@ std::optional<Snapshot> ColorMatrixFilterContents::RenderFilter(
}
out_texture->SetLabel("ColorMatrixFilter Texture");

return Snapshot{
.texture = out_texture,
.transform = input_snapshot->transform,
.sampler_descriptor = input_snapshot->sampler_descriptor,
.opacity = GetAbsorbOpacity() ? 1.0f : input_snapshot->opacity};
return Contents::EntityFromSnapshot(
Snapshot{.texture = out_texture,
.transform = input_snapshot->transform,
.sampler_descriptor = input_snapshot->sampler_descriptor,
.opacity = GetAbsorbOpacity() ? 1.0f : input_snapshot->opacity},
entity.GetBlendMode(), entity.GetStencilDepth());
}

} // namespace impeller
11 changes: 5 additions & 6 deletions impeller/entity/contents/filters/color_matrix_filter_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ class ColorMatrixFilterContents final : public ColorFilterContents {

private:
// |FilterContents|
std::optional<Snapshot> RenderFilter(
const FilterInput::Vector& input_textures,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const override;
std::optional<Entity> RenderFilter(const FilterInput::Vector& input_textures,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage) const override;

ColorMatrix matrix_;

Expand Down
45 changes: 21 additions & 24 deletions impeller/entity/contents/filters/filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,11 @@ bool FilterContents::Render(const ContentContext& renderer,

// Run the filter.

auto maybe_snapshot = RenderToSnapshot(renderer, entity);
if (!maybe_snapshot.has_value()) {
return false;
auto maybe_entity = GetEntity(renderer, entity);
if (!maybe_entity.has_value()) {
return true;
}
auto& snapshot = maybe_snapshot.value();

// Draw the result texture, respecting the transform and clip stack.

auto texture_rect = Rect::MakeSize(snapshot.texture->GetSize());
auto contents = TextureContents::MakeRect(texture_rect);
contents->SetTexture(snapshot.texture);
contents->SetSamplerDescriptor(snapshot.sampler_descriptor);
contents->SetSourceRect(texture_rect);
contents->SetOpacity(snapshot.opacity);

Entity e;
e.SetBlendMode(entity.GetBlendMode());
e.SetStencilDepth(entity.GetStencilDepth());
e.SetTransformation(snapshot.transform);
return contents->Render(renderer, e, pass);
return maybe_entity->Render(renderer, pass);
}

std::optional<Rect> FilterContents::GetLocalCoverage(
Expand Down Expand Up @@ -234,11 +219,8 @@ std::optional<Rect> FilterContents::GetFilterCoverage(
return result;
}

std::optional<Snapshot> FilterContents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled) const {
std::optional<Entity> FilterContents::GetEntity(const ContentContext& renderer,
const Entity& entity) const {
Entity entity_with_local_transform = entity;
entity_with_local_transform.SetTransformation(
GetTransform(entity.GetTransformation()));
Expand All @@ -252,6 +234,21 @@ std::optional<Snapshot> FilterContents::RenderToSnapshot(
effect_transform_, coverage.value());
}

std::optional<Snapshot> FilterContents::RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled) const {
// Resolve the render instruction (entity) from the filter and render it to a
// snapshot.
if (std::optional<Entity> result = GetEntity(renderer, entity);
result.has_value()) {
return result->GetContents()->RenderToSnapshot(renderer, result.value());
}

return std::nullopt;
}

Matrix FilterContents::GetLocalTransform(const Matrix& parent_transform) const {
return Matrix();
}
Expand Down
Loading