diff --git a/impeller/entity/contents/color_source_contents.h b/impeller/entity/contents/color_source_contents.h index 83fe120aed0fe..f3f7281301f14 100644 --- a/impeller/entity/contents/color_source_contents.h +++ b/impeller/entity/contents/color_source_contents.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_ #define FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_ +#include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/contents.h" #include "impeller/entity/geometry/geometry.h" #include "impeller/geometry/matrix.h" @@ -100,6 +101,102 @@ class ColorSourceContents : public Contents { // |Contents| void SetInheritedOpacity(Scalar opacity) override; + protected: + using BindFragmentCallback = std::function; + using PipelineBuilderMethod = std::shared_ptr> ( + impeller::ContentContext::*)(ContentContextOptions) const; + using PipelineBuilderCallback = + std::function>( + ContentContextOptions)>; + + template + bool DrawGeometry(GeometryResult geometry_result, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass, + const PipelineBuilderCallback& pipeline_callback, + typename VertexShaderT::FrameInfo frame_info, + const BindFragmentCallback& bind_fragment_callback) const { + auto options = OptionsFromPassAndEntity(pass, entity); + + // If overdraw prevention is enabled (like when drawing stroke paths), we + // increment the stencil buffer as we draw, preventing overlapping fragments + // from drawing. Afterwards, we need to append another draw call to clean up + // the stencil buffer (happens below in this method). + if (geometry_result.prevent_overdraw) { + options.stencil_mode = + ContentContextOptions::StencilMode::kLegacyClipIncrement; + } + options.primitive_type = geometry_result.type; + pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); + pass.SetStencilReference(entity.GetClipDepth()); + + // Take the pre-populated vertex shader uniform struct and set managed + // values. + frame_info.depth = entity.GetShaderClipDepth(); + frame_info.mvp = geometry_result.transform; + + VertexShaderT::BindFrameInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); + + // The reason we need to have a callback mechanism here is that this routine + // may insert draw calls before the main draw call below. For example, for + // sufficiently complex paths we may opt to use stencil-then-cover to avoid + // tessellation. + if (!bind_fragment_callback(pass)) { + return false; + } + + pass.SetPipeline(pipeline_callback(options)); + + if (!pass.Draw().ok()) { + return false; + } + + // If we performed overdraw prevention, a subsection of the clip heightmap + // was incremented by 1 in order to self-clip. So simply append a clip + // restore to clean it up. + if (geometry_result.prevent_overdraw) { + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); + } + return true; + } + + template + bool DrawPositions(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass, + const PipelineBuilderCallback& pipeline_callback, + typename VertexShaderT::FrameInfo frame_info, + const BindFragmentCallback& bind_pipeline_callback) const { + GeometryResult geometry_result = + GetGeometry()->GetPositionBuffer(renderer, entity, pass); + + return DrawGeometry(std::move(geometry_result), renderer, + entity, pass, pipeline_callback, + frame_info, bind_pipeline_callback); + } + + template + bool DrawPositionsAndUVs( + Rect texture_coverage, + const Matrix& effect_transform, + const ContentContext& renderer, + const Entity& entity, + RenderPass& pass, + const PipelineBuilderCallback& pipeline_callback, + typename VertexShaderT::FrameInfo frame_info, + const BindFragmentCallback& bind_pipeline_callback) const { + auto geometry_result = GetGeometry()->GetPositionUVBuffer( + texture_coverage, effect_transform, renderer, entity, pass); + + return DrawGeometry(std::move(geometry_result), renderer, + entity, pass, pipeline_callback, + frame_info, bind_pipeline_callback); + } + private: std::shared_ptr geometry_; Matrix inverse_matrix_; diff --git a/impeller/entity/contents/conical_gradient_contents.cc b/impeller/entity/contents/conical_gradient_contents.cc index 9bd5e1ee61091..de3013d14f3f8 100644 --- a/impeller/entity/contents/conical_gradient_contents.cc +++ b/impeller/entity/contents/conical_gradient_contents.cc @@ -64,62 +64,45 @@ bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer, using VS = ConicalGradientSSBOFillPipeline::VertexShader; using FS = ConicalGradientSSBOFillPipeline::FragmentShader; - FS::FragInfo frag_info; - frag_info.center = center_; - frag_info.radius = radius_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.alpha = GetOpacityFactor(); - if (focus_) { - frag_info.focus = focus_.value(); - frag_info.focus_radius = focus_radius_; - } else { - frag_info.focus = center_; - frag_info.focus_radius = 0.0; - } - - auto& host_buffer = renderer.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_); - - frag_info.colors_length = colors.size(); - auto color_buffer = - host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), - DefaultUniformAlignment()); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = pass.GetOrthographicTransform() * entity.GetTransform(); frame_info.matrix = GetInverseEffectTransform(); - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - pass.SetCommandLabel("ConicalGradientSSBOFill"); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetPipeline(renderer.GetConicalGradientSSBOFillPipeline(options)); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - FS::BindColorData(pass, color_buffer); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetConicalGradientSSBOFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.radius = radius_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.alpha = GetOpacityFactor(); + if (focus_) { + frag_info.focus = focus_.value(); + frag_info.focus_radius = focus_radius_; + } else { + frag_info.focus = center_; + frag_info.focus_radius = 0.0; + } + + auto& host_buffer = renderer.GetTransientsBuffer(); + auto colors = CreateGradientColors(colors_, stops_); + + frag_info.colors_length = colors.size(); + auto color_buffer = + host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), + DefaultUniformAlignment()); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindColorData(pass, color_buffer); + + pass.SetCommandLabel("ConicalGradientSSBOFill"); + return true; + }); } bool ConicalGradientContents::RenderTexture(const ContentContext& renderer, @@ -135,64 +118,52 @@ bool ConicalGradientContents::RenderTexture(const ContentContext& renderer, return false; } - FS::FragInfo frag_info; - frag_info.center = center_; - frag_info.radius = radius_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.texture_sampler_y_coord_scale = gradient_texture->GetYCoordScale(); - frag_info.alpha = GetOpacityFactor(); - frag_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width, - 0.5 / gradient_texture->GetSize().height); - if (focus_) { - frag_info.focus = focus_.value(); - frag_info.focus_radius = focus_radius_; - } else { - frag_info.focus = center_; - frag_info.focus_radius = 0.0; - } - auto geometry_result = GetGeometry()->GetPositionBuffer(renderer, entity, pass); VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = geometry_result.transform; frame_info.matrix = GetInverseEffectTransform(); - pass.SetCommandLabel("ConicalGradientFill"); - pass.SetStencilReference(entity.GetClipDepth()); - - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - pass.SetPipeline(renderer.GetConicalGradientFillPipeline(options)); - - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - SamplerDescriptor sampler_desc; - sampler_desc.min_filter = MinMagFilter::kLinear; - sampler_desc.mag_filter = MinMagFilter::kLinear; - FS::BindTextureSampler( - pass, gradient_texture, - renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetConicalGradientFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &gradient_texture](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.radius = radius_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.texture_sampler_y_coord_scale = + gradient_texture->GetYCoordScale(); + frag_info.alpha = GetOpacityFactor(); + frag_info.half_texel = + Vector2(0.5 / gradient_texture->GetSize().width, + 0.5 / gradient_texture->GetSize().height); + if (focus_) { + frag_info.focus = focus_.value(); + frag_info.focus_radius = focus_radius_; + } else { + frag_info.focus = center_; + frag_info.focus_radius = 0.0; + } + + pass.SetCommandLabel("ConicalGradientFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + SamplerDescriptor sampler_desc; + sampler_desc.min_filter = MinMagFilter::kLinear; + sampler_desc.mag_filter = MinMagFilter::kLinear; + FS::BindTextureSampler( + pass, gradient_texture, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_desc)); + + return true; + }); } bool ConicalGradientContents::ApplyColorFilter( diff --git a/impeller/entity/contents/linear_gradient_contents.cc b/impeller/entity/contents/linear_gradient_contents.cc index cb319b327f43a..8b7f8ad0bc9f8 100644 --- a/impeller/entity/contents/linear_gradient_contents.cc +++ b/impeller/entity/contents/linear_gradient_contents.cc @@ -5,7 +5,6 @@ #include "linear_gradient_contents.h" #include "impeller/core/formats.h" -#include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/content_context.h" #include "impeller/entity/contents/gradient_generator.h" #include "impeller/entity/entity.h" @@ -69,64 +68,49 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer, using VS = LinearGradientFillPipeline::VertexShader; using FS = LinearGradientFillPipeline::FragmentShader; - auto gradient_data = CreateGradientBuffer(colors_, stops_); - auto gradient_texture = - CreateGradientTexture(gradient_data, renderer.GetContext()); - if (gradient_texture == nullptr) { - return false; - } - - FS::FragInfo frag_info; - frag_info.start_point = start_point_; - frag_info.end_point = end_point_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.texture_sampler_y_coord_scale = gradient_texture->GetYCoordScale(); - frag_info.alpha = GetOpacityFactor(); - frag_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width, - 0.5 / gradient_texture->GetSize().height); - - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = geometry_result.transform; frame_info.matrix = GetInverseEffectTransform(); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - SamplerDescriptor sampler_desc; - sampler_desc.min_filter = MinMagFilter::kLinear; - sampler_desc.mag_filter = MinMagFilter::kLinear; - - pass.SetCommandLabel("LinearGradientFill"); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetPipeline(renderer.GetLinearGradientFillPipeline(options)); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindTextureSampler( - pass, std::move(gradient_texture), - renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetLinearGradientFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer](RenderPass& pass) { + auto gradient_data = CreateGradientBuffer(colors_, stops_); + auto gradient_texture = + CreateGradientTexture(gradient_data, renderer.GetContext()); + if (gradient_texture == nullptr) { + return false; + } + + FS::FragInfo frag_info; + frag_info.start_point = start_point_; + frag_info.end_point = end_point_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.texture_sampler_y_coord_scale = + gradient_texture->GetYCoordScale(); + frag_info.alpha = GetOpacityFactor(); + frag_info.half_texel = + Vector2(0.5 / gradient_texture->GetSize().width, + 0.5 / gradient_texture->GetSize().height); + + pass.SetCommandLabel("LinearGradientFill"); + + SamplerDescriptor sampler_desc; + sampler_desc.min_filter = MinMagFilter::kLinear; + sampler_desc.mag_filter = MinMagFilter::kLinear; + + FS::BindTextureSampler( + pass, std::move(gradient_texture), + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_desc)); + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + return true; + }); } bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, @@ -135,55 +119,39 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, using VS = LinearGradientSSBOFillPipeline::VertexShader; using FS = LinearGradientSSBOFillPipeline::FragmentShader; - FS::FragInfo frag_info; - frag_info.start_point = start_point_; - frag_info.end_point = end_point_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.alpha = GetOpacityFactor(); - - auto& host_buffer = renderer.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_); - - frag_info.colors_length = colors.size(); - auto color_buffer = - host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), - DefaultUniformAlignment()); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = pass.GetOrthographicTransform() * entity.GetTransform(); frame_info.matrix = GetInverseEffectTransform(); - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - pass.SetCommandLabel("LinearGradientSSBOFill"); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetPipeline(renderer.GetLinearGradientSSBOFillPipeline(options)); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - FS::BindColorData(pass, color_buffer); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetLinearGradientSSBOFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.start_point = start_point_; + frag_info.end_point = end_point_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.alpha = GetOpacityFactor(); + + auto& host_buffer = renderer.GetTransientsBuffer(); + auto colors = CreateGradientColors(colors_, stops_); + + frag_info.colors_length = colors.size(); + auto color_buffer = + host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), + DefaultUniformAlignment()); + + pass.SetCommandLabel("LinearGradientSSBOFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindColorData(pass, color_buffer); + + return true; + }); } bool LinearGradientContents::ApplyColorFilter( diff --git a/impeller/entity/contents/radial_gradient_contents.cc b/impeller/entity/contents/radial_gradient_contents.cc index 8bed872c08a65..d60130ced04ea 100644 --- a/impeller/entity/contents/radial_gradient_contents.cc +++ b/impeller/entity/contents/radial_gradient_contents.cc @@ -70,55 +70,38 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, using VS = RadialGradientSSBOFillPipeline::VertexShader; using FS = RadialGradientSSBOFillPipeline::FragmentShader; - FS::FragInfo frag_info; - frag_info.center = center_; - frag_info.radius = radius_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.alpha = GetOpacityFactor(); - - auto& host_buffer = renderer.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_); - - frag_info.colors_length = colors.size(); - auto color_buffer = - host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), - DefaultUniformAlignment()); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = pass.GetOrthographicTransform() * entity.GetTransform(); frame_info.matrix = GetInverseEffectTransform(); - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - pass.SetCommandLabel("RadialGradientSSBOFill"); - pass.SetPipeline(renderer.GetRadialGradientSSBOFillPipeline(options)); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - FS::BindColorData(pass, color_buffer); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetRadialGradientSSBOFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.radius = radius_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.alpha = GetOpacityFactor(); + + auto& host_buffer = renderer.GetTransientsBuffer(); + auto colors = CreateGradientColors(colors_, stops_); + + frag_info.colors_length = colors.size(); + auto color_buffer = + host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), + DefaultUniformAlignment()); + + pass.SetCommandLabel("RadialGradientSSBOFill"); + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindColorData(pass, color_buffer); + + return true; + }); } bool RadialGradientContents::RenderTexture(const ContentContext& renderer, @@ -134,57 +117,46 @@ bool RadialGradientContents::RenderTexture(const ContentContext& renderer, return false; } - FS::FragInfo frag_info; - frag_info.center = center_; - frag_info.radius = radius_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.texture_sampler_y_coord_scale = gradient_texture->GetYCoordScale(); - frag_info.alpha = GetOpacityFactor(); - frag_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width, - 0.5 / gradient_texture->GetSize().height); - - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = geometry_result.transform; frame_info.matrix = GetInverseEffectTransform(); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - SamplerDescriptor sampler_desc; - sampler_desc.min_filter = MinMagFilter::kLinear; - sampler_desc.mag_filter = MinMagFilter::kLinear; - - pass.SetCommandLabel("RadialGradientFill"); - pass.SetPipeline(renderer.GetRadialGradientFillPipeline(options)); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - FS::BindTextureSampler( - pass, gradient_texture, - renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); VS::BindFrameInfo(pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetRadialGradientFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &gradient_texture](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.radius = radius_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.texture_sampler_y_coord_scale = + gradient_texture->GetYCoordScale(); + frag_info.alpha = GetOpacityFactor(); + frag_info.half_texel = + Vector2(0.5 / gradient_texture->GetSize().width, + 0.5 / gradient_texture->GetSize().height); + + SamplerDescriptor sampler_desc; + sampler_desc.min_filter = MinMagFilter::kLinear; + sampler_desc.mag_filter = MinMagFilter::kLinear; + + pass.SetCommandLabel("RadialGradientFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindTextureSampler( + pass, gradient_texture, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_desc)); + + return true; + }); } bool RadialGradientContents::ApplyColorFilter( diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index 75eedb80939fb..d51b89bf9e94e 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -13,7 +13,6 @@ #include "impeller/core/formats.h" #include "impeller/core/runtime_types.h" #include "impeller/core/shader_types.h" -#include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/content_context.h" #include "impeller/entity/runtime_effect.vert.h" #include "impeller/renderer/capabilities.h" @@ -82,18 +81,9 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, runtime_stage_->GetEntrypoint(), ShaderStage::kFragment); //-------------------------------------------------------------------------- - /// Resolve geometry and content context options. + /// Resolve runtime stage function. /// - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - if (function && runtime_stage_->IsDirty()) { renderer.ClearCachedRuntimeEffectPipeline(runtime_stage_->GetEntrypoint()); context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(function); @@ -145,194 +135,187 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, using VS = RuntimeEffectVertexShader; - pass.SetCommandLabel("RuntimeEffectContents"); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - - //-------------------------------------------------------------------------- - /// Vertex stage uniforms. - /// - - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = geometry_result.transform; - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - //-------------------------------------------------------------------------- /// Fragment stage uniforms. /// - size_t minimum_sampler_index = 100000000; - size_t buffer_index = 0; - size_t buffer_offset = 0; - std::vector descriptor_set_layouts; - for (const auto& uniform : runtime_stage_->GetUniforms()) { - std::shared_ptr metadata = MakeShaderMetadata(uniform); - - switch (uniform.type) { - case kSampledImage: { - // Sampler uniforms are ordered in the IPLR according to their - // declaration and the uniform location reflects the correct offset to - // be mapped to - except that it may include all proceeding float - // uniforms. For example, a float sampler that comes after 4 float - // uniforms may have a location of 4. To convert to the actual offset we - // need to find the largest location assigned to a float uniform and - // then subtract this from all uniform locations. This is more or less - // the same operation we previously performed in the shader compiler. - minimum_sampler_index = - std::min(minimum_sampler_index, uniform.location); - break; - } - case kFloat: { - FML_DCHECK(renderer.GetContext()->GetBackendType() != - Context::BackendType::kVulkan) - << "Uniform " << uniform.name - << " had unexpected type kFloat for Vulkan backend."; - size_t alignment = - std::max(uniform.bit_width / 8, DefaultUniformAlignment()); - auto buffer_view = renderer.GetTransientsBuffer().Emplace( - uniform_data_->data() + buffer_offset, uniform.GetSize(), - alignment); - - ShaderUniformSlot uniform_slot; - uniform_slot.name = uniform.name.c_str(); - uniform_slot.ext_res_0 = uniform.location; - pass.BindResource(ShaderStage::kFragment, - DescriptorType::kUniformBuffer, uniform_slot, - metadata, buffer_view); - buffer_index++; - buffer_offset += uniform.GetSize(); - break; - } - case kStruct: { - FML_DCHECK(renderer.GetContext()->GetBackendType() == - Context::BackendType::kVulkan); - descriptor_set_layouts.emplace_back(DescriptorSetLayout{ - static_cast(uniform.location), - DescriptorType::kUniformBuffer, - ShaderStage::kFragment, - }); - ShaderUniformSlot uniform_slot; - uniform_slot.name = uniform.name.c_str(); - uniform_slot.binding = uniform.location; - - std::vector uniform_buffer; - uniform_buffer.reserve(uniform.struct_layout.size()); - size_t uniform_byte_index = 0u; - for (const auto& byte_type : uniform.struct_layout) { - if (byte_type == 0) { - uniform_buffer.push_back(0.f); - } else if (byte_type == 1) { - uniform_buffer.push_back(reinterpret_cast( - uniform_data_->data())[uniform_byte_index++]); - } else { - FML_UNREACHABLE(); - } + BindFragmentCallback bind_callback = [this, &renderer, &context, + &descriptor_set_layouts]( + RenderPass& pass) { + size_t minimum_sampler_index = 100000000; + size_t buffer_index = 0; + size_t buffer_offset = 0; + + for (const auto& uniform : runtime_stage_->GetUniforms()) { + std::shared_ptr metadata = MakeShaderMetadata(uniform); + + switch (uniform.type) { + case kSampledImage: { + // Sampler uniforms are ordered in the IPLR according to their + // declaration and the uniform location reflects the correct offset to + // be mapped to - except that it may include all proceeding float + // uniforms. For example, a float sampler that comes after 4 float + // uniforms may have a location of 4. To convert to the actual offset + // we need to find the largest location assigned to a float uniform + // and then subtract this from all uniform locations. This is more or + // less the same operation we previously performed in the shader + // compiler. + minimum_sampler_index = + std::min(minimum_sampler_index, uniform.location); + break; } + case kFloat: { + FML_DCHECK(renderer.GetContext()->GetBackendType() != + Context::BackendType::kVulkan) + << "Uniform " << uniform.name + << " had unexpected type kFloat for Vulkan backend."; + size_t alignment = + std::max(uniform.bit_width / 8, DefaultUniformAlignment()); + auto buffer_view = renderer.GetTransientsBuffer().Emplace( + uniform_data_->data() + buffer_offset, uniform.GetSize(), + alignment); + + ShaderUniformSlot uniform_slot; + uniform_slot.name = uniform.name.c_str(); + uniform_slot.ext_res_0 = uniform.location; + pass.BindResource(ShaderStage::kFragment, + DescriptorType::kUniformBuffer, uniform_slot, + metadata, buffer_view); + buffer_index++; + buffer_offset += uniform.GetSize(); + break; + } + case kStruct: { + FML_DCHECK(renderer.GetContext()->GetBackendType() == + Context::BackendType::kVulkan); + descriptor_set_layouts.emplace_back(DescriptorSetLayout{ + static_cast(uniform.location), + DescriptorType::kUniformBuffer, + ShaderStage::kFragment, + }); + ShaderUniformSlot uniform_slot; + uniform_slot.name = uniform.name.c_str(); + uniform_slot.binding = uniform.location; + + std::vector uniform_buffer; + uniform_buffer.reserve(uniform.struct_layout.size()); + size_t uniform_byte_index = 0u; + for (const auto& byte_type : uniform.struct_layout) { + if (byte_type == 0) { + uniform_buffer.push_back(0.f); + } else if (byte_type == 1) { + uniform_buffer.push_back(reinterpret_cast( + uniform_data_->data())[uniform_byte_index++]); + } else { + FML_UNREACHABLE(); + } + } - size_t alignment = std::max(sizeof(float) * uniform_buffer.size(), - DefaultUniformAlignment()); + size_t alignment = std::max(sizeof(float) * uniform_buffer.size(), + DefaultUniformAlignment()); - auto buffer_view = renderer.GetTransientsBuffer().Emplace( - reinterpret_cast(uniform_buffer.data()), - sizeof(float) * uniform_buffer.size(), alignment); - pass.BindResource(ShaderStage::kFragment, - DescriptorType::kUniformBuffer, uniform_slot, - ShaderMetadata{}, buffer_view); + auto buffer_view = renderer.GetTransientsBuffer().Emplace( + reinterpret_cast(uniform_buffer.data()), + sizeof(float) * uniform_buffer.size(), alignment); + pass.BindResource(ShaderStage::kFragment, + DescriptorType::kUniformBuffer, uniform_slot, + ShaderMetadata{}, buffer_view); + } } } - } - size_t sampler_index = 0; - for (const auto& uniform : runtime_stage_->GetUniforms()) { - std::shared_ptr metadata = MakeShaderMetadata(uniform); + size_t sampler_index = 0; + for (const auto& uniform : runtime_stage_->GetUniforms()) { + std::shared_ptr metadata = MakeShaderMetadata(uniform); - switch (uniform.type) { - case kSampledImage: { - FML_DCHECK(sampler_index < texture_inputs_.size()); - auto& input = texture_inputs_[sampler_index]; + switch (uniform.type) { + case kSampledImage: { + FML_DCHECK(sampler_index < texture_inputs_.size()); + auto& input = texture_inputs_[sampler_index]; - const std::unique_ptr& sampler = - context->GetSamplerLibrary()->GetSampler(input.sampler_descriptor); + const std::unique_ptr& sampler = + context->GetSamplerLibrary()->GetSampler( + input.sampler_descriptor); - SampledImageSlot image_slot; - image_slot.name = uniform.name.c_str(); + SampledImageSlot image_slot; + image_slot.name = uniform.name.c_str(); - uint32_t sampler_binding_location = 0u; - if (!descriptor_set_layouts.empty()) { - sampler_binding_location = descriptor_set_layouts.back().binding + 1; - } + uint32_t sampler_binding_location = 0u; + if (!descriptor_set_layouts.empty()) { + sampler_binding_location = + descriptor_set_layouts.back().binding + 1; + } - descriptor_set_layouts.emplace_back(DescriptorSetLayout{ - sampler_binding_location, - DescriptorType::kSampledImage, - ShaderStage::kFragment, - }); + descriptor_set_layouts.emplace_back(DescriptorSetLayout{ + sampler_binding_location, + DescriptorType::kSampledImage, + ShaderStage::kFragment, + }); - image_slot.binding = sampler_binding_location; - image_slot.texture_index = uniform.location - minimum_sampler_index; - pass.BindResource(ShaderStage::kFragment, DescriptorType::kSampledImage, - image_slot, *metadata, input.texture, sampler); + image_slot.binding = sampler_binding_location; + image_slot.texture_index = uniform.location - minimum_sampler_index; + pass.BindResource(ShaderStage::kFragment, + DescriptorType::kSampledImage, image_slot, + *metadata, input.texture, sampler); - sampler_index++; - break; + sampler_index++; + break; + } + default: + continue; } - default: - continue; } - } + return true; + }; /// Now that the descriptor set layouts are known, get the pipeline. - auto create_callback = - [&]() -> std::shared_ptr> { - PipelineDescriptor desc; - desc.SetLabel("Runtime Stage"); - desc.AddStageEntrypoint( - library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex)); - desc.AddStageEntrypoint(library->GetFunction( - runtime_stage_->GetEntrypoint(), ShaderStage::kFragment)); - auto vertex_descriptor = std::make_shared(); - vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs, - VS::kInterleavedBufferLayout); - vertex_descriptor->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts); - vertex_descriptor->RegisterDescriptorSetLayouts( - descriptor_set_layouts.data(), descriptor_set_layouts.size()); - desc.SetVertexDescriptor(std::move(vertex_descriptor)); - desc.SetColorAttachmentDescriptor( - 0u, {.format = color_attachment_format, .blending_enabled = true}); - - desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{}); - desc.SetStencilPixelFormat(stencil_attachment_format); - - desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{}); - desc.SetDepthPixelFormat(stencil_attachment_format); - - options.ApplyToPipelineDescriptor(desc); - auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get(); - if (!pipeline) { - VALIDATION_LOG << "Failed to get or create runtime effect pipeline."; - return nullptr; - } - return pipeline; - }; - - pass.SetPipeline(renderer.GetCachedRuntimeEffectPipeline( - runtime_stage_->GetEntrypoint(), options, create_callback)); + PipelineBuilderCallback pipeline_callback = [&](ContentContextOptions + options) { + // Pipeline creation callback for the cache handler to call. + auto create_callback = + [&]() -> std::shared_ptr> { + PipelineDescriptor desc; + desc.SetLabel("Runtime Stage"); + desc.AddStageEntrypoint( + library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex)); + desc.AddStageEntrypoint(library->GetFunction( + runtime_stage_->GetEntrypoint(), ShaderStage::kFragment)); + auto vertex_descriptor = std::make_shared(); + vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs, + VS::kInterleavedBufferLayout); + vertex_descriptor->RegisterDescriptorSetLayouts( + VS::kDescriptorSetLayouts); + vertex_descriptor->RegisterDescriptorSetLayouts( + descriptor_set_layouts.data(), descriptor_set_layouts.size()); + desc.SetVertexDescriptor(std::move(vertex_descriptor)); + desc.SetColorAttachmentDescriptor( + 0u, {.format = color_attachment_format, .blending_enabled = true}); + + desc.SetStencilAttachmentDescriptors(StencilAttachmentDescriptor{}); + desc.SetStencilPixelFormat(stencil_attachment_format); + + desc.SetDepthStencilAttachmentDescriptor(DepthAttachmentDescriptor{}); + desc.SetDepthPixelFormat(stencil_attachment_format); + + options.ApplyToPipelineDescriptor(desc); + auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get(); + if (!pipeline) { + VALIDATION_LOG << "Failed to get or create runtime effect pipeline."; + return nullptr; + } - if (!pass.Draw().ok()) { - return false; - } + return pipeline; + }; + return renderer.GetCachedRuntimeEffectPipeline( + runtime_stage_->GetEntrypoint(), options, create_callback); + }; - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + return ColorSourceContents::DrawPositions(renderer, entity, pass, + pipeline_callback, + VS::FrameInfo{}, bind_callback); } } // namespace impeller diff --git a/impeller/entity/contents/solid_color_contents.cc b/impeller/entity/contents/solid_color_contents.cc index 707e771e79f86..a8b46e297052e 100644 --- a/impeller/entity/contents/solid_color_contents.cc +++ b/impeller/entity/contents/solid_color_contents.cc @@ -4,7 +4,6 @@ #include "solid_color_contents.h" -#include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/content_context.h" #include "impeller/entity/entity.h" #include "impeller/entity/geometry/geometry.h" @@ -52,39 +51,19 @@ bool SolidColorContents::Render(const ContentContext& renderer, auto capture = entity.GetCapture().CreateChild("SolidColorContents"); using VS = SolidFillPipeline::VertexShader; - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - - options.primitive_type = geometry_result.type; - - pass.SetCommandLabel("Solid Fill"); - pass.SetPipeline(renderer.GetSolidFillPipeline(options)); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - pass.SetStencilReference(entity.GetClipDepth()); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = capture.AddMatrix("Transform", geometry_result.transform); frame_info.color = capture.AddColor("Color", GetColor()).Premultiply(); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetSolidFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [](RenderPass& pass) { + pass.SetCommandLabel("Solid Fill"); + return true; + }); } std::unique_ptr SolidColorContents::Make(const Path& path, diff --git a/impeller/entity/contents/sweep_gradient_contents.cc b/impeller/entity/contents/sweep_gradient_contents.cc index 29fbe935eaa6e..af43454ae9c2d 100644 --- a/impeller/entity/contents/sweep_gradient_contents.cc +++ b/impeller/entity/contents/sweep_gradient_contents.cc @@ -76,57 +76,42 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, using VS = SweepGradientSSBOFillPipeline::VertexShader; using FS = SweepGradientSSBOFillPipeline::FragmentShader; - FS::FragInfo frag_info; - frag_info.center = center_; - frag_info.bias = bias_; - frag_info.scale = scale_; - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.alpha = GetOpacityFactor(); - - auto& host_buffer = renderer.GetTransientsBuffer(); - auto colors = CreateGradientColors(colors_, stops_); - - frag_info.colors_length = colors.size(); - auto color_buffer = - host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), - DefaultUniformAlignment()); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = pass.GetOrthographicTransform() * entity.GetTransform(); frame_info.matrix = GetInverseEffectTransform(); - - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - pass.SetCommandLabel("SweepGradientSSBOFill"); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetPipeline(renderer.GetSweepGradientSSBOFillPipeline(options)); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - FS::BindColorData(pass, color_buffer); VS::BindFrameInfo(pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetSweepGradientSSBOFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.bias = bias_; + frag_info.scale = scale_; + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.alpha = GetOpacityFactor(); + + auto& host_buffer = renderer.GetTransientsBuffer(); + auto colors = CreateGradientColors(colors_, stops_); + + frag_info.colors_length = colors.size(); + auto color_buffer = + host_buffer.Emplace(colors.data(), colors.size() * sizeof(StopData), + DefaultUniformAlignment()); + + pass.SetCommandLabel("SweepGradientSSBOFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindColorData(pass, color_buffer); + + return true; + }); } bool SweepGradientContents::RenderTexture(const ContentContext& renderer, @@ -142,59 +127,44 @@ bool SweepGradientContents::RenderTexture(const ContentContext& renderer, return false; } - FS::FragInfo frag_info; - frag_info.center = center_; - frag_info.bias = bias_; - frag_info.scale = scale_; - frag_info.texture_sampler_y_coord_scale = gradient_texture->GetYCoordScale(); - frag_info.tile_mode = static_cast(tile_mode_); - frag_info.decal_border_color = decal_border_color_; - frag_info.alpha = GetOpacityFactor(); - frag_info.half_texel = Vector2(0.5 / gradient_texture->GetSize().width, - 0.5 / gradient_texture->GetSize().height); - - auto geometry_result = - GetGeometry()->GetPositionBuffer(renderer, entity, pass); - VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = geometry_result.transform; frame_info.matrix = GetInverseEffectTransform(); - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; - - SamplerDescriptor sampler_desc; - sampler_desc.min_filter = MinMagFilter::kLinear; - sampler_desc.mag_filter = MinMagFilter::kLinear; - - pass.SetCommandLabel("SweepGradientFill"); - pass.SetStencilReference(entity.GetClipDepth()); - pass.SetPipeline(renderer.GetSweepGradientFillPipeline(options)); - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - - FS::BindFragInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); - VS::BindFrameInfo(pass, - renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); - FS::BindTextureSampler( - pass, gradient_texture, - renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer](ContentContextOptions options) { + return renderer.GetSweepGradientFillPipeline(options); + }; + return ColorSourceContents::DrawPositions( + renderer, entity, pass, pipeline_callback, frame_info, + [this, &renderer, &gradient_texture](RenderPass& pass) { + FS::FragInfo frag_info; + frag_info.center = center_; + frag_info.bias = bias_; + frag_info.scale = scale_; + frag_info.texture_sampler_y_coord_scale = + gradient_texture->GetYCoordScale(); + frag_info.tile_mode = static_cast(tile_mode_); + frag_info.decal_border_color = decal_border_color_; + frag_info.alpha = GetOpacityFactor(); + frag_info.half_texel = + Vector2(0.5 / gradient_texture->GetSize().width, + 0.5 / gradient_texture->GetSize().height); + + SamplerDescriptor sampler_desc; + sampler_desc.min_filter = MinMagFilter::kLinear; + sampler_desc.mag_filter = MinMagFilter::kLinear; + + pass.SetCommandLabel("SweepGradientFill"); + + FS::BindFragInfo( + pass, renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindTextureSampler( + pass, gradient_texture, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_desc)); + + return true; + }); } bool SweepGradientContents::ApplyColorFilter( diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc index 732e27ec25d20..5e73d93b96f39 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -5,9 +5,7 @@ #include "impeller/entity/contents/tiled_texture_contents.h" #include "fml/logging.h" -#include "impeller/entity/contents/clip_contents.h" #include "impeller/entity/contents/content_context.h" -#include "impeller/entity/geometry/geometry.h" #include "impeller/entity/texture_fill.vert.h" #include "impeller/entity/tiled_texture_fill.frag.h" #include "impeller/entity/tiled_texture_fill_external.frag.h" @@ -129,107 +127,95 @@ bool TiledTextureContents::Render(const ContentContext& renderer, bool is_external_texture = texture_->GetTextureDescriptor().type == TextureType::kTextureExternalOES; - auto& host_buffer = renderer.GetTransientsBuffer(); - - auto geometry_result = GetGeometry()->GetPositionUVBuffer( - Rect::MakeSize(texture_size), GetInverseEffectTransform(), renderer, - entity, pass); bool uses_emulated_tile_mode = UsesEmulatedTileMode(renderer.GetDeviceCapabilities()); VS::FrameInfo frame_info; - frame_info.depth = entity.GetShaderClipDepth(); - frame_info.mvp = geometry_result.transform; frame_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale(); frame_info.alpha = GetOpacityFactor(); - if (uses_emulated_tile_mode) { - pass.SetCommandLabel("TiledTextureFill"); - } else { - pass.SetCommandLabel("TextureFill"); - } - - pass.SetStencilReference(entity.GetClipDepth()); - - auto options = OptionsFromPassAndEntity(pass, entity); - if (geometry_result.prevent_overdraw) { - options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; - } - options.primitive_type = geometry_result.type; + PipelineBuilderMethod pipeline_method; #ifdef IMPELLER_ENABLE_OPENGLES if (is_external_texture) { - pass.SetPipeline(renderer.GetTiledTextureExternalPipeline(options)); + pipeline_method = &ContentContext::GetTiledTextureExternalPipeline; } else { - pass.SetPipeline(uses_emulated_tile_mode - ? renderer.GetTiledTexturePipeline(options) - : renderer.GetTexturePipeline(options)); + pipeline_method = uses_emulated_tile_mode + ? &ContentContext::GetTiledTexturePipeline + : &ContentContext::GetTexturePipeline; } #else - pass.SetPipeline(uses_emulated_tile_mode - ? renderer.GetTiledTexturePipeline(options) - : renderer.GetTexturePipeline(options)); + pipeline_method = uses_emulated_tile_mode + ? &ContentContext::GetTiledTexturePipeline + : &ContentContext::GetTexturePipeline; #endif // IMPELLER_ENABLE_OPENGLES - pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer)); - VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info)); - - if (is_external_texture) { - FSExternal::FragInfo frag_info; - frag_info.x_tile_mode = static_cast(x_tile_mode_); - frag_info.y_tile_mode = static_cast(y_tile_mode_); - FSExternal::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info)); - } else if (uses_emulated_tile_mode) { - FS::FragInfo frag_info; - frag_info.x_tile_mode = static_cast(x_tile_mode_); - frag_info.y_tile_mode = static_cast(y_tile_mode_); - FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info)); - } - - if (is_external_texture) { - SamplerDescriptor sampler_desc; - // OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, so we - // emulate all other tile modes here by remapping the texture coordinates. - sampler_desc.width_address_mode = SamplerAddressMode::kClampToEdge; - sampler_desc.height_address_mode = SamplerAddressMode::kClampToEdge; - - // Also, external textures cannot be bound to color filters, so ignore this - // case for now. - FML_DCHECK(!color_filter_) - << "Color filters are not currently supported for external textures."; - - FSExternal::BindSAMPLEREXTERNALOESTextureSampler( - pass, texture_, - renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - } else { - if (color_filter_) { - auto filtered_texture = CreateFilterTexture(renderer); - if (!filtered_texture) { - return false; - } - FS::BindTextureSampler( - pass, filtered_texture, - renderer.GetContext()->GetSamplerLibrary()->GetSampler( - CreateSamplerDescriptor(renderer.GetDeviceCapabilities()))); - } else { - FS::BindTextureSampler( - pass, texture_, - renderer.GetContext()->GetSamplerLibrary()->GetSampler( - CreateSamplerDescriptor(renderer.GetDeviceCapabilities()))); - } - } - - if (!pass.Draw().ok()) { - return false; - } - - if (geometry_result.prevent_overdraw) { - auto restore = ClipRestoreContents(); - restore.SetRestoreCoverage(GetCoverage(entity)); - return restore.Render(renderer, entity, pass); - } - return true; + PipelineBuilderCallback pipeline_callback = + [&renderer, &pipeline_method](ContentContextOptions options) { + return (renderer.*pipeline_method)(options); + }; + return ColorSourceContents::DrawPositionsAndUVs( + Rect::MakeSize(texture_size), GetInverseEffectTransform(), renderer, + entity, pass, pipeline_callback, frame_info, + [this, &renderer, &is_external_texture, + &uses_emulated_tile_mode](RenderPass& pass) { + auto& host_buffer = renderer.GetTransientsBuffer(); + + if (uses_emulated_tile_mode) { + pass.SetCommandLabel("TiledTextureFill"); + } else { + pass.SetCommandLabel("TextureFill"); + } + + if (is_external_texture) { + FSExternal::FragInfo frag_info; + frag_info.x_tile_mode = static_cast(x_tile_mode_); + frag_info.y_tile_mode = static_cast(y_tile_mode_); + FSExternal::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info)); + } else if (uses_emulated_tile_mode) { + FS::FragInfo frag_info; + frag_info.x_tile_mode = static_cast(x_tile_mode_); + frag_info.y_tile_mode = static_cast(y_tile_mode_); + FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info)); + } + + if (is_external_texture) { + SamplerDescriptor sampler_desc; + // OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, so + // we emulate all other tile modes here by remapping the texture + // coordinates. + sampler_desc.width_address_mode = SamplerAddressMode::kClampToEdge; + sampler_desc.height_address_mode = SamplerAddressMode::kClampToEdge; + + // Also, external textures cannot be bound to color filters, so ignore + // this case for now. + FML_DCHECK(!color_filter_) << "Color filters are not currently " + "supported for external textures."; + + FSExternal::BindSAMPLEREXTERNALOESTextureSampler( + pass, texture_, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_desc)); + } else { + if (color_filter_) { + auto filtered_texture = CreateFilterTexture(renderer); + if (!filtered_texture) { + return false; + } + FS::BindTextureSampler( + pass, filtered_texture, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + CreateSamplerDescriptor(renderer.GetDeviceCapabilities()))); + } else { + FS::BindTextureSampler( + pass, texture_, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + CreateSamplerDescriptor(renderer.GetDeviceCapabilities()))); + } + } + + return true; + }); } std::optional TiledTextureContents::RenderToSnapshot( diff --git a/impeller/entity/geometry/geometry.cc b/impeller/entity/geometry/geometry.cc index 65b2b43c583c0..fe38adfa86625 100644 --- a/impeller/entity/geometry/geometry.cc +++ b/impeller/entity/geometry/geometry.cc @@ -7,6 +7,7 @@ #include #include +#include "fml/status.h" #include "impeller/entity/contents/content_context.h" #include "impeller/entity/geometry/circle_geometry.h" #include "impeller/entity/geometry/cover_geometry.h"