Skip to content

Commit

Permalink
[Impeller] Add AbsorbOpacity enum.
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero committed Sep 14, 2023
1 parent 2cd34d2 commit 1617874
Show file tree
Hide file tree
Showing 13 changed files with 104 additions and 64 deletions.
8 changes: 4 additions & 4 deletions impeller/aiks/color_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ BlendColorFilter::~BlendColorFilter() = default;

std::shared_ptr<ColorFilterContents> BlendColorFilter::WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
auto filter =
ColorFilterContents::MakeBlend(blend_mode_, {std::move(input)}, color_);
filter->SetAbsorbOpacity(absorb_opacity);
Expand Down Expand Up @@ -73,7 +73,7 @@ MatrixColorFilter::~MatrixColorFilter() = default;

std::shared_ptr<ColorFilterContents> MatrixColorFilter::WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
auto filter =
ColorFilterContents::MakeColorMatrix({std::move(input)}, color_matrix_);
filter->SetAbsorbOpacity(absorb_opacity);
Expand Down Expand Up @@ -101,7 +101,7 @@ SrgbToLinearColorFilter::~SrgbToLinearColorFilter() = default;
std::shared_ptr<ColorFilterContents>
SrgbToLinearColorFilter::WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
auto filter = ColorFilterContents::MakeSrgbToLinearFilter({std::move(input)});
filter->SetAbsorbOpacity(absorb_opacity);
return filter;
Expand All @@ -127,7 +127,7 @@ LinearToSrgbColorFilter::~LinearToSrgbColorFilter() = default;
std::shared_ptr<ColorFilterContents>
LinearToSrgbColorFilter::WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
auto filter = ColorFilterContents::MakeSrgbToLinearFilter({std::move(input)});
filter->SetAbsorbOpacity(absorb_opacity);
return filter;
Expand Down
10 changes: 5 additions & 5 deletions impeller/aiks/color_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ColorFilter {
/// treated as color information.
virtual std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const = 0;
ColorFilterContents::AbsorbOpacity absorb_opacity) const = 0;

/// @brief Returns a function that can be used to filter unpremultiplied
/// Impeller Colors on the CPU.
Expand All @@ -65,7 +65,7 @@ class BlendColorFilter final : public ColorFilter {
// |ColorFilter|
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const override;
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;

// |ColorFilter|
ColorFilterProc GetCPUColorFilterProc() const override;
Expand All @@ -91,7 +91,7 @@ class MatrixColorFilter final : public ColorFilter {
// |ColorFilter|
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const override;
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;

// |ColorFilter|
ColorFilterProc GetCPUColorFilterProc() const override;
Expand All @@ -116,7 +116,7 @@ class SrgbToLinearColorFilter final : public ColorFilter {
// |ColorFilter|
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const override;
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;

// |ColorFilter|
ColorFilterProc GetCPUColorFilterProc() const override;
Expand All @@ -138,7 +138,7 @@ class LinearToSrgbColorFilter final : public ColorFilter {
// |ColorFilter|
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
std::shared_ptr<FilterInput> input,
bool absorb_opacity) const override;
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;

// |ColorFilter|
ColorFilterProc GetCPUColorFilterProc() const override;
Expand Down
5 changes: 3 additions & 2 deletions impeller/aiks/color_source.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "impeller/aiks/paint.h"
#include "impeller/core/sampler_descriptor.h"
#include "impeller/entity/contents/conical_gradient_contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/linear_gradient_contents.h"
#include "impeller/entity/contents/radial_gradient_contents.h"
#include "impeller/entity/contents/runtime_effect_contents.h"
Expand Down Expand Up @@ -182,8 +183,8 @@ ColorSource ColorSource::MakeImage(std::shared_ptr<Texture> texture,
if (paint.color_filter) {
TiledTextureContents::ColorFilterProc filter_proc =
[color_filter = paint.color_filter](FilterInput::Ref input) {
return color_filter->WrapWithGPUColorFilter(std::move(input),
false);
return color_filter->WrapWithGPUColorFilter(
std::move(input), ColorFilterContents::AbsorbOpacity::kNo);
};
contents->SetColorFilter(filter_proc);
}
Expand Down
4 changes: 3 additions & 1 deletion impeller/aiks/image_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#include "impeller/aiks/image_filter.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"

Expand Down Expand Up @@ -175,7 +176,8 @@ ColorImageFilter::~ColorImageFilter() = default;

std::shared_ptr<FilterContents> ColorImageFilter::WrapInput(
const FilterInput::Ref& input) const {
return color_filter_->WrapWithGPUColorFilter(input, false);
return color_filter_->WrapWithGPUColorFilter(
input, ColorFilterContents::AbsorbOpacity::kNo);
}

std::shared_ptr<ImageFilter> ColorImageFilter::Clone() const {
Expand Down
9 changes: 5 additions & 4 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ std::shared_ptr<Contents> Paint::CreateContentsForGeometry(

std::shared_ptr<Contents> Paint::WithFilters(
std::shared_ptr<Contents> input) const {
input = WithColorFilter(input, /*absorb_opacity=*/true);
input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
input = WithInvertFilter(input);
input = WithImageFilter(input, Matrix(), /*is_subpass=*/false);
return input;
Expand All @@ -68,7 +68,7 @@ std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
std::shared_ptr<Contents> input,
const Matrix& effect_transform) const {
input = WithImageFilter(input, effect_transform, /*is_subpass=*/true);
input = WithColorFilter(input, /*absorb_opacity=*/true);
input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
return input;
}

Expand Down Expand Up @@ -96,7 +96,7 @@ std::shared_ptr<Contents> Paint::WithImageFilter(

std::shared_ptr<Contents> Paint::WithColorFilter(
std::shared_ptr<Contents> input,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
// Image input types will directly set their color filter,
// if any. See `TiledTextureContents.SetColorFilter`.
if (color_source.GetType() == ColorSource::Type::kImage) {
Expand Down Expand Up @@ -179,7 +179,8 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(

if (color_filter) {
color_contents = color_filter->WrapWithGPUColorFilter(
FilterInput::Make(color_source_contents), true);
FilterInput::Make(color_source_contents),
ColorFilterContents::AbsorbOpacity::kYes);
}

/// 5. Composite the color source with the blurred mask.
Expand Down
6 changes: 4 additions & 2 deletions impeller/aiks/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ struct Paint {
const Matrix& effect_transform,
bool is_subpass) const;

std::shared_ptr<Contents> WithColorFilter(std::shared_ptr<Contents> input,
bool absorb_opacity = false) const;
std::shared_ptr<Contents> WithColorFilter(
std::shared_ptr<Contents> input,
ColorFilterContents::AbsorbOpacity absorb_opacity =
ColorFilterContents::AbsorbOpacity::kNo) const;

std::shared_ptr<Contents> WithInvertFilter(
std::shared_ptr<Contents> input) const;
Expand Down
72 changes: 45 additions & 27 deletions impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "impeller/entity/contents/anonymous_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/entity.h"
Expand Down Expand Up @@ -76,7 +77,7 @@ static std::optional<Entity> AdvancedBlend(
const Rect& coverage,
BlendMode blend_mode,
std::optional<Color> foreground_color,
bool absorb_opacity,
ColorFilterContents::AbsorbOpacity absorb_opacity,
PipelineProc pipeline_proc,
std::optional<Scalar> alpha) {
using VS = typename TPipeline::VertexShader;
Expand Down Expand Up @@ -184,7 +185,10 @@ static std::optional<Entity> AdvancedBlend(
dst_sampler_descriptor);
FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, dst_sampler);
frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
blend_info.dst_input_alpha = absorb_opacity ? dst_snapshot->opacity : 1.0;
blend_info.dst_input_alpha =
absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
? dst_snapshot->opacity
: 1.0;

if (foreground_color.has_value()) {
blend_info.color_factor = 1;
Expand Down Expand Up @@ -227,14 +231,17 @@ static std::optional<Entity> AdvancedBlend(
}

return Entity::FromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(subpass_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)},
Snapshot{
.texture = out_texture,
.transform = Matrix::MakeTranslation(subpass_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 == ColorFilterContents::AbsorbOpacity::kYes
? 1.0f
: dst_snapshot->opacity) *
alpha.value_or(1.0)},
entity.GetBlendMode(), entity.GetStencilDepth());
}

Expand All @@ -246,7 +253,7 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
Color foreground_color,
BlendMode blend_mode,
std::optional<Scalar> alpha,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
auto dst_snapshot =
input->GetSnapshot("ForegroundAdvancedBlend", renderer, entity);
if (!dst_snapshot.has_value()) {
Expand Down Expand Up @@ -353,7 +360,9 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, dst_sampler);
frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
blend_info.dst_input_alpha =
absorb_opacity ? dst_snapshot->opacity * alpha.value_or(1.0) : 1.0;
absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
? dst_snapshot->opacity * alpha.value_or(1.0)
: 1.0;

blend_info.color_factor = 1;
blend_info.color = foreground_color;
Expand Down Expand Up @@ -395,7 +404,7 @@ std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
Color foreground_color,
BlendMode blend_mode,
std::optional<Scalar> alpha,
bool absorb_opacity) const {
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
if (blend_mode == BlendMode::kClear) {
return std::nullopt;
}
Expand Down Expand Up @@ -477,7 +486,9 @@ std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
dst_snapshot->texture->GetYCoordScale();

frag_info.input_alpha =
absorb_opacity ? dst_snapshot->opacity * alpha.value_or(1.0) : 1.0;
absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
? dst_snapshot->opacity * alpha.value_or(1.0)
: 1.0;
frag_info.output_alpha = 1.0;

auto blend_coefficients =
Expand Down Expand Up @@ -520,7 +531,7 @@ static std::optional<Entity> PipelineBlend(
const Rect& coverage,
BlendMode blend_mode,
std::optional<Color> foreground_color,
bool absorb_opacity,
ColorFilterContents::AbsorbOpacity absorb_opacity,
std::optional<Scalar> alpha) {
using VS = BlendPipeline::VertexShader;
using FS = BlendPipeline::FragmentShader;
Expand Down Expand Up @@ -589,7 +600,10 @@ static std::optional<Entity> PipelineBlend(
input->texture->GetYCoordScale();

FS::FragInfo frag_info;
frag_info.input_alpha = absorb_opacity ? input->opacity : 1.0;
frag_info.input_alpha =
absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
? input->opacity
: 1.0;
FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));

Expand Down Expand Up @@ -647,14 +661,17 @@ static std::optional<Entity> PipelineBlend(
}

return Entity::FromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(subpass_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)},
Snapshot{
.texture = out_texture,
.transform = Matrix::MakeTranslation(subpass_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 == ColorFilterContents::AbsorbOpacity::kYes
? 1.0f
: dst_snapshot->opacity) *
alpha.value_or(1.0)},
entity.GetBlendMode(), entity.GetStencilDepth());
}

Expand All @@ -663,7 +680,8 @@ static std::optional<Entity> PipelineBlend(
advanced_blend_proc_ = \
[](const FilterInput::Vector& inputs, const ContentContext& renderer, \
const Entity& entity, const Rect& coverage, BlendMode blend_mode, \
std::optional<Color> fg_color, bool absorb_opacity, \
std::optional<Color> fg_color, \
ColorFilterContents::AbsorbOpacity absorb_opacity, \
std::optional<Scalar> alpha) { \
PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \
return AdvancedBlend<Blend##mode##Pipeline>( \
Expand Down Expand Up @@ -726,7 +744,7 @@ std::optional<Entity> BlendFilterContents::RenderFilter(

if (blend_mode_ <= Entity::kLastPipelineBlendMode) {
if (inputs.size() == 1 && foreground_color_.has_value() &&
GetAbsorbOpacity()) {
GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) {
return CreateForegroundPorterDuffBlend(
inputs[0], renderer, entity, coverage, foreground_color_.value(),
blend_mode_, GetAlpha(), GetAbsorbOpacity());
Expand All @@ -737,7 +755,7 @@ std::optional<Entity> BlendFilterContents::RenderFilter(

if (blend_mode_ <= Entity::kLastAdvancedBlendMode) {
if (inputs.size() == 1 && foreground_color_.has_value() &&
GetAbsorbOpacity()) {
GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) {
return CreateForegroundAdvancedBlend(
inputs[0], renderer, entity, coverage, foreground_color_.value(),
blend_mode_, GetAlpha(), GetAbsorbOpacity());
Expand Down
22 changes: 11 additions & 11 deletions impeller/entity/contents/filters/blend_filter_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ std::optional<BlendMode> InvertPorterDuffBlend(BlendMode blend_mode);

class BlendFilterContents : public ColorFilterContents {
public:
using AdvancedBlendProc =
std::function<std::optional<Entity>(const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
const Rect& coverage,
BlendMode blend_mode,
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,
BlendMode blend_mode,
std::optional<Color> foreground_color,
ColorFilterContents::AbsorbOpacity absorb_opacity,
std::optional<Scalar> alpha)>;

BlendFilterContents();

Expand Down Expand Up @@ -75,7 +75,7 @@ class BlendFilterContents : public ColorFilterContents {
Color foreground_color,
BlendMode blend_mode,
std::optional<Scalar> alpha,
bool absorb_opacity) const;
ColorFilterContents::AbsorbOpacity absorb_opacity) const;

/// @brief Optimized porter-duff blend that avoids a second subpass when there
/// is only a single input and a foreground color.
Expand All @@ -89,7 +89,7 @@ class BlendFilterContents : public ColorFilterContents {
Color foreground_color,
BlendMode blend_mode,
std::optional<Scalar> alpha,
bool absorb_opacity) const;
ColorFilterContents::AbsorbOpacity absorb_opacity) const;

BlendMode blend_mode_ = BlendMode::kSourceOver;
AdvancedBlendProc advanced_blend_proc_;
Expand Down
5 changes: 3 additions & 2 deletions impeller/entity/contents/filters/color_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ ColorFilterContents::ColorFilterContents() = default;

ColorFilterContents::~ColorFilterContents() = default;

void ColorFilterContents::SetAbsorbOpacity(bool absorb_opacity) {
void ColorFilterContents::SetAbsorbOpacity(AbsorbOpacity absorb_opacity) {
absorb_opacity_ = absorb_opacity;
}

bool ColorFilterContents::GetAbsorbOpacity() const {
ColorFilterContents::AbsorbOpacity ColorFilterContents::GetAbsorbOpacity()
const {
return absorb_opacity_;
}

Expand Down
Loading

0 comments on commit 1617874

Please sign in to comment.