diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 338372d4227c1..19fcdcfa36442 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1313,8 +1313,6 @@ ORIGIN: ../../../flutter/impeller/entity/geometry.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/geometry.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/inline_pass_context.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/entity/shaders/atlas_fill.frag + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/impeller/entity/shaders/atlas_fill.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag + ../../../flutter/LICENSE @@ -3791,8 +3789,6 @@ FILE: ../../../flutter/impeller/entity/geometry.cc FILE: ../../../flutter/impeller/entity/geometry.h 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 diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 835748d0110d7..536fb378df21a 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -379,7 +379,7 @@ void Canvas::DrawTextFrame(const TextFrame& text_frame, void Canvas::DrawVertices(std::unique_ptr vertices, BlendMode blend_mode, - Paint paint) { + const Paint& paint) { Entity entity; entity.SetTransformation(GetCurrentTransformation()); entity.SetStencilDepth(GetStencilDepth()); diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index 456948b99139c..aacbe513b2e99 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -99,7 +99,7 @@ class Canvas { void DrawVertices(std::unique_ptr vertices, BlendMode blend_mode, - Paint paint); + const Paint& paint); void DrawAtlas(const std::shared_ptr& atlas, std::vector transforms, diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 24702f3a82709..261a89a0ac27c 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -8,8 +8,6 @@ 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", diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc index b983d29e9c261..69a4f07679c94 100644 --- a/impeller/entity/contents/atlas_contents.cc +++ b/impeller/entity/contents/atlas_contents.cc @@ -5,16 +5,19 @@ #include #include -#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/contents/filters/color_filter_contents.h" +#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity.h" +#include "impeller/entity/geometry.h" +#include "impeller/entity/texture_fill.frag.h" +#include "impeller/entity/texture_fill.vert.h" +#include "impeller/renderer/formats.h" #include "impeller/renderer/render_pass.h" +#include "impeller/renderer/sampler_library.h" +#include "impeller/renderer/vertex_buffer_builder.h" namespace impeller { @@ -47,7 +50,6 @@ void AtlasContents::SetAlpha(Scalar alpha) { } void AtlasContents::SetBlendMode(BlendMode blend_mode) { - // TODO(jonahwilliams): blending of colors with texture. blend_mode_ = blend_mode; } @@ -59,7 +61,10 @@ std::optional AtlasContents::GetCoverage(const Entity& entity) const { if (cull_rect_.has_value()) { return cull_rect_.value().TransformBounds(entity.GetTransformation()); } + return ComputeBoundingBox().TransformBounds(entity.GetTransformation()); +} +Rect AtlasContents::ComputeBoundingBox() const { Rect bounding_box = {}; for (size_t i = 0; i < texture_coords_.size(); i++) { auto matrix = transforms_[i]; @@ -67,7 +72,7 @@ std::optional AtlasContents::GetCoverage(const Entity& entity) const { auto bounds = Rect::MakeSize(sample_rect.size).TransformBounds(matrix); bounding_box = bounds.Union(bounding_box); } - return bounding_box.TransformBounds(entity.GetTransformation()); + return bounding_box; } void AtlasContents::SetSamplerDescriptor(SamplerDescriptor desc) { @@ -78,30 +83,98 @@ const SamplerDescriptor& AtlasContents::GetSamplerDescriptor() const { return sampler_descriptor_; } +const std::vector& AtlasContents::GetTransforms() const { + return transforms_; +} + +const std::vector& AtlasContents::GetTextureCoordinates() const { + return texture_coords_; +} + +const std::vector& AtlasContents::GetColors() const { + return colors_; +} + bool AtlasContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - if (texture_ == nullptr) { + if (texture_ == nullptr || blend_mode_ == BlendMode::kClear || + alpha_ <= 0.0) { return true; } - using VS = AtlasFillVertexShader; - using FS = AtlasFillFragmentShader; + // Ensure that we use the actual computed bounds and not a cull-rect + // approximation of them. + auto coverage = ComputeBoundingBox(); - const auto texture_size = texture_->GetSize(); - if (texture_size.IsEmpty()) { - return true; + if (blend_mode_ == BlendMode::kSource || colors_.size() == 0) { + auto child_contents = AtlasTextureContents(*this); + child_contents.SetAlpha(alpha_); + child_contents.SetCoverage(coverage); + return child_contents.Render(renderer, entity, pass); + } + if (blend_mode_ == BlendMode::kDestination) { + auto child_contents = AtlasColorContents(*this); + child_contents.SetAlpha(alpha_); + child_contents.SetCoverage(coverage); + return child_contents.Render(renderer, entity, pass); } + auto src_contents = std::make_shared(*this); + src_contents->SetCoverage(coverage); + + auto dst_contents = std::make_shared(*this); + dst_contents->SetCoverage(coverage); + + // For some reason this looks backwards compared to Skia unless + // we reverse the src/dst. + auto contents = ColorFilterContents::MakeBlend( + blend_mode_, + {FilterInput::Make(dst_contents), FilterInput::Make(src_contents)}); + contents->SetAlpha(alpha_); + return contents->Render(renderer, entity, pass); +} + +// AtlasTextureContents +// --------------------------------------------------------- + +AtlasTextureContents::AtlasTextureContents(const AtlasContents& parent) + : parent_(parent) {} + +AtlasTextureContents::~AtlasTextureContents() {} + +std::optional AtlasTextureContents::GetCoverage( + const Entity& entity) const { + return coverage_.TransformBounds(entity.GetTransformation()); +} + +void AtlasTextureContents::SetAlpha(Scalar alpha) { + alpha_ = alpha; +} + +void AtlasTextureContents::SetCoverage(Rect coverage) { + coverage_ = coverage; +} + +bool AtlasTextureContents::Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = TextureFillVertexShader; + using FS = TextureFillFragmentShader; + + auto texture = parent_.GetTexture(); + auto texture_coords = parent_.GetTextureCoordinates(); + auto transforms = parent_.GetTransforms(); + + const auto texture_size = texture->GetSize(); VertexBufferBuilder vertex_builder; - vertex_builder.Reserve(texture_coords_.size() * 6); + 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(); + for (size_t i = 0; i < texture_coords.size(); i++) { + auto sample_rect = texture_coords[i]; + auto matrix = transforms[i]; auto transformed_points = Rect::MakeSize(sample_rect.size).GetTransformedPoints(matrix); @@ -112,7 +185,6 @@ bool AtlasContents::Render(const ContentContext& renderer, (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); } } @@ -121,6 +193,9 @@ bool AtlasContents::Render(const ContentContext& renderer, return true; } + Command cmd; + cmd.label = "AtlasTexture"; + auto& host_buffer = pass.GetTransientsBuffer(); VS::VertInfo vert_info; @@ -128,24 +203,93 @@ bool AtlasContents::Render(const ContentContext& renderer, entity.GetTransformation(); FS::FragInfo frag_info; - frag_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale(); - frag_info.has_vertex_color = colors_.size() > 0 ? 1.0 : 0.0; + frag_info.texture_sampler_y_coord_scale = texture->GetYCoordScale(); frag_info.alpha = alpha_; - Command cmd; - cmd.label = "DrawAtlas"; - cmd.pipeline = - renderer.GetAtlasPipeline(OptionsFromPassAndEntity(pass, entity)); + auto options = OptionsFromPassAndEntity(pass, entity); + cmd.pipeline = renderer.GetTexturePipeline(options); 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_, + FS::BindTextureSampler(cmd, texture, renderer.GetContext()->GetSamplerLibrary()->GetSampler( - sampler_descriptor_)); - pass.AddCommand(std::move(cmd)); + parent_.GetSamplerDescriptor())); + return pass.AddCommand(std::move(cmd)); +} + +// AtlasColorContents +// --------------------------------------------------------- + +AtlasColorContents::AtlasColorContents(const AtlasContents& parent) + : parent_(parent) {} - return true; +AtlasColorContents::~AtlasColorContents() {} + +std::optional AtlasColorContents::GetCoverage( + const Entity& entity) const { + return coverage_.TransformBounds(entity.GetTransformation()); +} + +void AtlasColorContents::SetAlpha(Scalar alpha) { + alpha_ = alpha; +} + +void AtlasColorContents::SetCoverage(Rect coverage) { + coverage_ = coverage; +} + +bool AtlasColorContents::Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + using VS = GeometryColorPipeline::VertexShader; + using FS = GeometryColorPipeline::FragmentShader; + + auto texture_coords = parent_.GetTextureCoordinates(); + auto transforms = parent_.GetTransforms(); + auto colors = parent_.GetColors(); + + VertexBufferBuilder vertex_builder; + vertex_builder.Reserve(texture_coords.size() * 6); + constexpr size_t indices[6] = {0, 1, 2, 1, 2, 3}; + for (size_t i = 0; i < texture_coords.size(); i++) { + auto sample_rect = texture_coords[i]; + auto matrix = transforms[i]; + 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.color = colors[i].Premultiply(); + vertex_builder.AppendVertex(data); + } + } + + if (!vertex_builder.HasVertices()) { + return true; + } + + Command cmd; + cmd.label = "AtlasColors"; + + auto& host_buffer = pass.GetTransientsBuffer(); + + VS::VertInfo vert_info; + vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(); + + FS::FragInfo frag_info; + frag_info.alpha = alpha_; + + auto opts = OptionsFromPassAndEntity(pass, entity); + opts.blend_mode = BlendMode::kSourceOver; + cmd.pipeline = renderer.GetGeometryColorPipeline(opts); + 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)); + return pass.AddCommand(std::move(cmd)); } } // namespace impeller diff --git a/impeller/entity/contents/atlas_contents.h b/impeller/entity/contents/atlas_contents.h index 7b879892da2a1..2313f3402f995 100644 --- a/impeller/entity/contents/atlas_contents.h +++ b/impeller/entity/contents/atlas_contents.h @@ -41,6 +41,12 @@ class AtlasContents final : public Contents { const SamplerDescriptor& GetSamplerDescriptor() const; + const std::vector& GetTransforms() const; + + const std::vector& GetTextureCoordinates() const; + + const std::vector& GetColors() const; + // |Contents| std::optional GetCoverage(const Entity& entity) const override; @@ -50,6 +56,8 @@ class AtlasContents final : public Contents { RenderPass& pass) const override; private: + Rect ComputeBoundingBox() const; + std::shared_ptr texture_; std::vector texture_coords_; std::vector colors_; @@ -62,4 +70,56 @@ class AtlasContents final : public Contents { FML_DISALLOW_COPY_AND_ASSIGN(AtlasContents); }; +class AtlasTextureContents final : public Contents { + public: + explicit AtlasTextureContents(const AtlasContents& parent); + + ~AtlasTextureContents() override; + + // |Contents| + std::optional GetCoverage(const Entity& entity) const override; + + // |Contents| + bool Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + void SetAlpha(Scalar alpha); + + void SetCoverage(Rect coverage); + + private: + const AtlasContents& parent_; + Scalar alpha_ = 1.0; + Rect coverage_; + + FML_DISALLOW_COPY_AND_ASSIGN(AtlasTextureContents); +}; + +class AtlasColorContents final : public Contents { + public: + explicit AtlasColorContents(const AtlasContents& parent); + + ~AtlasColorContents() override; + + // |Contents| + std::optional GetCoverage(const Entity& entity) const override; + + // |Contents| + bool Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + void SetAlpha(Scalar alpha); + + void SetCoverage(Rect coverage); + + private: + const AtlasContents& parent_; + Scalar alpha_ = 1.0; + Rect coverage_; + + FML_DISALLOW_COPY_AND_ASSIGN(AtlasColorContents); +}; + } // namespace impeller diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index c6158d87f857e..1f0f8c4c37130 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -225,7 +225,6 @@ ContentContext::ContentContext(std::shared_ptr context) CreateDefaultPipeline(*context_); geometry_position_pipelines_[{}] = CreateDefaultPipeline(*context_); - atlas_pipelines_[{}] = CreateDefaultPipeline(*context_); yuv_to_rgb_filter_pipelines_[{}] = CreateDefaultPipeline(*context_); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index a23584339164a..e8cabf188c246 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -27,8 +27,6 @@ #include "impeller/entity/advanced_blend_saturation.frag.h" #include "impeller/entity/advanced_blend_screen.frag.h" #include "impeller/entity/advanced_blend_softlight.frag.h" -#include "impeller/entity/atlas_fill.frag.h" -#include "impeller/entity/atlas_fill.vert.h" #include "impeller/entity/blend.frag.h" #include "impeller/entity/blend.vert.h" #include "impeller/entity/border_mask_blur.frag.h" @@ -166,8 +164,6 @@ using GlyphAtlasPipeline = RenderPipelineT; using GlyphAtlasSdfPipeline = RenderPipelineT; -using AtlasPipeline = - RenderPipelineT; // Instead of requiring new shaders for clips, the solid fill stages are used // to redirect writing to the stencil instead of color attachments. using ClipPipeline = @@ -335,11 +331,6 @@ class ContentContext { return GetPipeline(geometry_position_pipelines_, opts); } - std::shared_ptr> GetAtlasPipeline( - ContentContextOptions opts) const { - return GetPipeline(atlas_pipelines_, opts); - } - std::shared_ptr> GetYUVToRGBFilterPipeline( ContentContextOptions opts) const { return GetPipeline(yuv_to_rgb_filter_pipelines_, opts); @@ -473,7 +464,6 @@ class ContentContext { mutable Variants clip_pipelines_; mutable Variants glyph_atlas_pipelines_; mutable Variants glyph_atlas_sdf_pipelines_; - mutable Variants atlas_pipelines_; mutable Variants geometry_position_pipelines_; mutable Variants geometry_color_pipelines_; mutable Variants yuv_to_rgb_filter_pipelines_; diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 38f8173e6580b..a46af9635be01 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -36,7 +36,8 @@ static std::optional AdvancedBlend( const Rect& coverage, std::optional foreground_color, bool absorb_opacity, - PipelineProc pipeline_proc) { + PipelineProc pipeline_proc, + std::optional alpha) { using VS = typename TPipeline::VertexShader; using FS = typename TPipeline::FragmentShader; @@ -109,7 +110,7 @@ static std::optional AdvancedBlend( auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({}); FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, sampler); blend_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale(); - blend_info.dst_input_alpha = absorb_opacity ? dst_snapshot->opacity : 1.0f; + blend_info.dst_input_alpha = absorb_opacity ? dst_snapshot->opacity : 1.0; if (foreground_color.has_value()) { blend_info.color_factor = 1; @@ -145,7 +146,8 @@ static std::optional AdvancedBlend( return Snapshot{.texture = out_texture, .transform = Matrix::MakeTranslation(coverage.origin), .sampler_descriptor = dst_snapshot->sampler_descriptor, - .opacity = absorb_opacity ? 1.0f : dst_snapshot->opacity}; + .opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) * + alpha.value_or(1.0)}; } static std::optional PipelineBlend( @@ -155,7 +157,8 @@ static std::optional PipelineBlend( const Rect& coverage, BlendMode pipeline_blend, std::optional foreground_color, - bool absorb_opacity) { + bool absorb_opacity, + std::optional alpha) { using VS = BlendPipeline::VertexShader; using FS = BlendPipeline::FragmentShader; @@ -264,20 +267,22 @@ static std::optional PipelineBlend( .transform = Matrix::MakeTranslation(coverage.origin), .sampler_descriptor = inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor, - .opacity = absorb_opacity ? 1.0f : dst_snapshot->opacity}; + .opacity = (absorb_opacity ? 1.0f : dst_snapshot->opacity) * + alpha.value_or(1.0)}; } -#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 fg_color, \ - bool absorb_opacity) { \ - PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ - return AdvancedBlend( \ - inputs, renderer, entity, coverage, fg_color, absorb_opacity, p); \ - }; \ +#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 fg_color, bool absorb_opacity, \ + std::optional alpha) { \ + PipelineProc p = &ContentContext::GetBlend##mode##Pipeline; \ + return AdvancedBlend(inputs, renderer, entity, \ + coverage, fg_color, \ + absorb_opacity, p, alpha); \ + }; \ break; void BlendFilterContents::SetBlendMode(BlendMode blend_mode) { @@ -328,17 +333,18 @@ std::optional BlendFilterContents::RenderFilter( if (inputs.size() == 1 && !foreground_color_.has_value()) { // Nothing to blend. return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource, - std::nullopt, GetAbsorbOpacity()); + std::nullopt, GetAbsorbOpacity(), GetAlpha()); } if (blend_mode_ <= Entity::kLastPipelineBlendMode) { return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_, - foreground_color_, GetAbsorbOpacity()); + foreground_color_, GetAbsorbOpacity(), GetAlpha()); } if (blend_mode_ <= Entity::kLastAdvancedBlendMode) { return advanced_blend_proc_(inputs, renderer, entity, coverage, - foreground_color_, GetAbsorbOpacity()); + foreground_color_, GetAbsorbOpacity(), + GetAlpha()); } FML_UNREACHABLE(); } diff --git a/impeller/entity/contents/filters/blend_filter_contents.h b/impeller/entity/contents/filters/blend_filter_contents.h index 5276eb81f05f1..47734ffa7b554 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.h +++ b/impeller/entity/contents/filters/blend_filter_contents.h @@ -17,7 +17,8 @@ class BlendFilterContents : public ColorFilterContents { const Entity& entity, const Rect& coverage, std::optional foreground_color, - bool absorb_opacity)>; + bool absorb_opacity, + std::optional alpha)>; BlendFilterContents(); diff --git a/impeller/entity/contents/filters/color_filter_contents.cc b/impeller/entity/contents/filters/color_filter_contents.cc index 64ba4e7139c8e..51de176698bba 100644 --- a/impeller/entity/contents/filters/color_filter_contents.cc +++ b/impeller/entity/contents/filters/color_filter_contents.cc @@ -90,4 +90,12 @@ bool ColorFilterContents::GetAbsorbOpacity() const { return absorb_opacity_; } +void ColorFilterContents::SetAlpha(Scalar alpha) { + alpha_ = alpha; +} + +std::optional ColorFilterContents::GetAlpha() const { + return alpha_; +} + } // namespace impeller diff --git a/impeller/entity/contents/filters/color_filter_contents.h b/impeller/entity/contents/filters/color_filter_contents.h index 775ad6f4253df..0099c16a6c282 100644 --- a/impeller/entity/contents/filters/color_filter_contents.h +++ b/impeller/entity/contents/filters/color_filter_contents.h @@ -34,8 +34,14 @@ class ColorFilterContents : public FilterContents { bool GetAbsorbOpacity() const; + /// @brief Sets an alpha that is applied to the final blended result. + void SetAlpha(Scalar alpha); + + std::optional GetAlpha() const; + private: bool absorb_opacity_ = false; + std::optional alpha_; FML_DISALLOW_COPY_AND_ASSIGN(ColorFilterContents); }; diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc index 3d0357ed9ae12..65b8c88762b48 100644 --- a/impeller/entity/contents/vertices_contents.cc +++ b/impeller/entity/contents/vertices_contents.cc @@ -83,6 +83,11 @@ bool VerticesContents::Render(const ContentContext& renderer, break; } } + using FS = GeometryColorPipeline::FragmentShader; + FS::FragInfo frag_info; + frag_info.alpha = 1.0; + FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + pass.AddCommand(std::move(cmd)); return true; diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index fffc7bb5c4fcb..6a1aa9b21657a 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -1244,7 +1244,7 @@ TEST_P(EntityTest, DrawAtlasNoColor) { ASSERT_TRUE(OpenPlaygroundHere(e)); } -TEST_P(EntityTest, DrawAtlasWithColor) { +TEST_P(EntityTest, DrawAtlasWithColorAdvanced) { // Draws the image as four squares stiched together. Because blend modes // aren't implented this ends up as four solid color blocks. auto atlas = CreateTextureForFixture("bay_bridge.jpg"); @@ -1271,7 +1271,43 @@ TEST_P(EntityTest, DrawAtlasWithColor) { contents->SetTextureCoordinates(std::move(texture_coordinates)); contents->SetTexture(atlas); contents->SetColors(colors); - contents->SetBlendMode(BlendMode::kSource); + contents->SetBlendMode(BlendMode::kModulate); + + Entity e; + e.SetTransformation(Matrix::MakeScale(GetContentScale())); + e.SetContents(contents); + + ASSERT_TRUE(OpenPlaygroundHere(e)); +} + +TEST_P(EntityTest, DrawAtlasWithColorSimple) { + // Draws the image as four squares stiched together. Because blend modes + // aren't implented this ends up as four solid color blocks. + auto atlas = CreateTextureForFixture("bay_bridge.jpg"); + auto size = atlas->GetSize(); + // Divide image into four quadrants. + Scalar half_width = size.width / 2; + Scalar half_height = size.height / 2; + std::vector texture_coordinates = { + Rect::MakeLTRB(0, 0, half_width, half_height), + Rect::MakeLTRB(half_width, 0, size.width, half_height), + Rect::MakeLTRB(0, half_height, half_width, size.height), + Rect::MakeLTRB(half_width, half_height, size.width, size.height)}; + // Position quadrants adjacent to eachother. + std::vector transforms = { + Matrix::MakeTranslation({0, 0, 0}), + Matrix::MakeTranslation({half_width, 0, 0}), + Matrix::MakeTranslation({0, half_height, 0}), + Matrix::MakeTranslation({half_width, half_height, 0})}; + std::vector colors = {Color::Red(), Color::Green(), Color::Blue(), + Color::Yellow()}; + std::shared_ptr contents = std::make_shared(); + + contents->SetTransforms(std::move(transforms)); + contents->SetTextureCoordinates(std::move(texture_coordinates)); + contents->SetTexture(atlas); + contents->SetColors(colors); + contents->SetBlendMode(BlendMode::kSourceATop); Entity e; e.SetTransformation(Matrix::MakeScale(GetContentScale())); diff --git a/impeller/entity/shaders/atlas_fill.frag b/impeller/entity/shaders/atlas_fill.frag deleted file mode 100644 index 4862343926a78..0000000000000 --- a/impeller/entity/shaders/atlas_fill.frag +++ /dev/null @@ -1,30 +0,0 @@ -// 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 -#include - -uniform sampler2D texture_sampler; - -uniform FragInfo { - float texture_sampler_y_coord_scale; - float has_vertex_color; - float alpha; -} -frag_info; - -in vec2 v_texture_coords; -in vec4 v_color; - -out vec4 frag_color; - -void main() { - vec4 sampled = IPSample(texture_sampler, v_texture_coords, - frag_info.texture_sampler_y_coord_scale); - if (frag_info.has_vertex_color == 1.0) { - frag_color = sampled.aaaa * v_color * frag_info.alpha; - } else { - frag_color = sampled * frag_info.alpha; - } -} diff --git a/impeller/entity/shaders/atlas_fill.vert b/impeller/entity/shaders/atlas_fill.vert deleted file mode 100644 index 6140ad98788a4..0000000000000 --- a/impeller/entity/shaders/atlas_fill.vert +++ /dev/null @@ -1,23 +0,0 @@ -// 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 - -uniform VertInfo { - mat4 mvp; -} -vert_info; - -in vec2 position; -in vec2 texture_coords; -in vec4 color; - -out vec2 v_texture_coords; -out vec4 v_color; - -void main() { - gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0); - v_texture_coords = texture_coords; - v_color = color; -} diff --git a/impeller/entity/shaders/vertices.frag b/impeller/entity/shaders/vertices.frag index c42e809ecc14d..029d33da06ba9 100644 --- a/impeller/entity/shaders/vertices.frag +++ b/impeller/entity/shaders/vertices.frag @@ -4,10 +4,15 @@ #include +uniform FragInfo { + float alpha; +} +frag_info; + in vec4 v_color; out vec4 frag_color; void main() { - frag_color = v_color; + frag_color = v_color * frag_info.alpha; }