Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions impeller/compiler/shader_lib/impeller/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ copy("impeller") {
"color.glsl",
"constants.glsl",
"gaussian.glsl",
"gradient.glsl",
"texture.glsl",
"transform.glsl",
"types.glsl",
Expand Down
35 changes: 35 additions & 0 deletions impeller/compiler/shader_lib/impeller/gradient.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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.

#ifndef GRADIENT_GLSL_
#define GRADIENT_GLSL_

#include <impeller/texture.glsl>

#define FIXED_GRADIENT_SIZE 16

/// Compute a gradient color from a buffer of up to 16 colors.
///
/// The provided value for `t` will be processed according to the `tile_mode`.
/// If the `tile_mode` is decal and t is less than 0 or greater than 1, vec4(0)
/// will be returned.
vec4 IPComputeFixedGradient(float t, vec4[FIXED_GRADIENT_SIZE] colors, float colors_length, float tile_mode) {
if ((t < 0.0 || t > 1.0) && tile_mode == kTileModeDecal) {
return vec4(0);
}

t = IPFloatTile(t, tile_mode);
if (colors_length == 2) {
return mix(colors[0], colors[1], t);
}

float rough_index = colors_length * t;
float lower_index = floor(rough_index);
int upper_index = int(ceil(rough_index));
float scale = rough_index - lower_index;

return mix(colors[int(lower_index)], colors[upper_index], scale);
}

#endif
3 changes: 3 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ impeller_shaders("entity_shaders") {
"shaders/linear_to_srgb_filter.frag",
"shaders/linear_to_srgb_filter.vert",
"shaders/linear_gradient_fill.frag",
"shaders/linear_gradient_fixed_fill.frag",
"shaders/morphology_filter.frag",
"shaders/morphology_filter.vert",
"shaders/position_color.vert",
"shaders/position_uv.vert",
"shaders/position.vert",
"shaders/radial_gradient_fill.frag",
"shaders/radial_gradient_fixed_fill.frag",
"shaders/rrect_blur.vert",
"shaders/rrect_blur.frag",
"shaders/runtime_effect.vert",
Expand All @@ -56,6 +58,7 @@ impeller_shaders("entity_shaders") {
"shaders/srgb_to_linear_filter.frag",
"shaders/srgb_to_linear_filter.vert",
"shaders/sweep_gradient_fill.frag",
"shaders/sweep_gradient_fixed_fill.frag",
"shaders/texture_fill.frag",
"shaders/texture_fill.vert",
"shaders/tiled_texture_fill.frag",
Expand Down
8 changes: 8 additions & 0 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
CreateDefaultPipeline<LinearGradientFillPipeline>(*context_);
radial_gradient_fill_pipelines_[{}] =
CreateDefaultPipeline<RadialGradientFillPipeline>(*context_);
#ifndef FML_OS_ANDROID
linear_gradient_fixed_fill_pipelines_[{}] =
CreateDefaultPipeline<LinearGradientFixedFillPipeline>(*context_);
radial_gradient_fixed_fill_pipelines_[{}] =
CreateDefaultPipeline<RadialGradientFixedFillPipeline>(*context_);
sweep_gradient_fixed_fill_pipelines_[{}] =
CreateDefaultPipeline<SweepGradientFixedFillPipeline>(*context_);
#endif // FML_OS_ANDROID
sweep_gradient_fill_pipelines_[{}] =
CreateDefaultPipeline<SweepGradientFillPipeline>(*context_);
rrect_blur_pipelines_[{}] =
Expand Down
39 changes: 39 additions & 0 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,21 @@
#include "impeller/entity/glyph_atlas_sdf.vert.h"
#include "impeller/entity/gradient_fill.vert.h"
#include "impeller/entity/linear_gradient_fill.frag.h"
#include "impeller/entity/linear_gradient_fixed_fill.frag.h"
#include "impeller/entity/linear_to_srgb_filter.frag.h"
#include "impeller/entity/linear_to_srgb_filter.vert.h"
#include "impeller/entity/morphology_filter.frag.h"
#include "impeller/entity/morphology_filter.vert.h"
#include "impeller/entity/radial_gradient_fill.frag.h"
#include "impeller/entity/radial_gradient_fixed_fill.frag.h"
#include "impeller/entity/rrect_blur.frag.h"
#include "impeller/entity/rrect_blur.vert.h"
#include "impeller/entity/solid_fill.frag.h"
#include "impeller/entity/solid_fill.vert.h"
#include "impeller/entity/srgb_to_linear_filter.frag.h"
#include "impeller/entity/srgb_to_linear_filter.vert.h"
#include "impeller/entity/sweep_gradient_fill.frag.h"
#include "impeller/entity/sweep_gradient_fixed_fill.frag.h"
#include "impeller/entity/texture_fill.frag.h"
#include "impeller/entity/texture_fill.vert.h"
#include "impeller/entity/tiled_texture_fill.frag.h"
Expand All @@ -82,6 +85,17 @@ using RadialGradientFillPipeline =
RenderPipelineT<GradientFillVertexShader, RadialGradientFillFragmentShader>;
using SweepGradientFillPipeline =
RenderPipelineT<GradientFillVertexShader, SweepGradientFillFragmentShader>;
#ifndef FML_OS_ANDROID
using LinearGradientFixedFillPipeline =
RenderPipelineT<GradientFillVertexShader,
LinearGradientFixedFillFragmentShader>;
using RadialGradientFixedFillPipeline =
RenderPipelineT<GradientFillVertexShader,
RadialGradientFixedFillFragmentShader>;
using SweepGradientFixedFillPipeline =
RenderPipelineT<GradientFillVertexShader,
SweepGradientFixedFillFragmentShader>;
#endif // FML_OS_ANDROID
using BlendPipeline = RenderPipelineT<BlendVertexShader, BlendFragmentShader>;
using RRectBlurPipeline =
RenderPipelineT<RrectBlurVertexShader, RrectBlurFragmentShader>;
Expand Down Expand Up @@ -210,6 +224,23 @@ class ContentContext {
return GetPipeline(linear_gradient_fill_pipelines_, opts);
}

#ifndef FML_OS_ANDROID
std::shared_ptr<Pipeline<PipelineDescriptor>>
GetLinearGradientFixedFillPipeline(ContentContextOptions opts) const {
return GetPipeline(linear_gradient_fixed_fill_pipelines_, opts);
}

std::shared_ptr<Pipeline<PipelineDescriptor>>
GetRadialGradientFixedFillPipeline(ContentContextOptions opts) const {
return GetPipeline(radial_gradient_fixed_fill_pipelines_, opts);
}

std::shared_ptr<Pipeline<PipelineDescriptor>>
GetSweepGradientFixedFillPipeline(ContentContextOptions opts) const {
return GetPipeline(sweep_gradient_fixed_fill_pipelines_, opts);
}
#endif // FML_OS_ANDROID

std::shared_ptr<Pipeline<PipelineDescriptor>> GetRadialGradientFillPipeline(
ContentContextOptions opts) const {
return GetPipeline(radial_gradient_fill_pipelines_, opts);
Expand Down Expand Up @@ -416,6 +447,14 @@ class ContentContext {
mutable Variants<LinearGradientFillPipeline> linear_gradient_fill_pipelines_;
mutable Variants<RadialGradientFillPipeline> radial_gradient_fill_pipelines_;
mutable Variants<SweepGradientFillPipeline> sweep_gradient_fill_pipelines_;
#ifndef FML_OS_ANDROID
mutable Variants<LinearGradientFixedFillPipeline>
linear_gradient_fixed_fill_pipelines_;
mutable Variants<RadialGradientFixedFillPipeline>
radial_gradient_fixed_fill_pipelines_;
mutable Variants<SweepGradientFixedFillPipeline>
sweep_gradient_fixed_fill_pipelines_;
#endif // FML_OS_ANDROID
mutable Variants<RRectBlurPipeline> rrect_blur_pipelines_;
mutable Variants<BlendPipeline> texture_blend_pipelines_;
mutable Variants<TexturePipeline> texture_pipelines_;
Expand Down
5 changes: 1 addition & 4 deletions impeller/entity/contents/gradient_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@

#include "flutter/fml/logging.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/geometry/gradient.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/texture.h"

namespace impeller {

std::shared_ptr<Texture> CreateGradientTexture(
const std::vector<Color>& colors,
const std::vector<Scalar>& stops,
const GradientData& gradient_data,
const std::shared_ptr<impeller::Context>& context) {
auto gradient_data = CreateGradientBuffer(colors, stops);
if (gradient_data.texture_size == 0) {
FML_DLOG(ERROR) << "Invalid gradient data.";
return nullptr;
Expand Down
6 changes: 3 additions & 3 deletions impeller/entity/contents/gradient_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "flutter/fml/macros.h"
#include "flutter/impeller/renderer/texture.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/gradient.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/point.h"

Expand All @@ -20,11 +21,10 @@ class Context;

/**
* @brief Create a host visible texture that contains the gradient defined
* by the provided colors and stops.
* by the provided gradient data.
*/
std::shared_ptr<Texture> CreateGradientTexture(
const std::vector<Color>& colors,
const std::vector<Scalar>& stops,
const GradientData& gradient_data,
const std::shared_ptr<impeller::Context>& context);

} // namespace impeller
71 changes: 70 additions & 1 deletion impeller/entity/contents/linear_gradient_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,27 @@ void LinearGradientContents::SetTileMode(Entity::TileMode tile_mode) {
bool LinearGradientContents::Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
#ifdef FML_OS_ANDROID
auto gradient_data = CreateGradientBuffer(colors_, stops_);
return RenderTexture(gradient_data, renderer, entity, pass);
#else
auto gradient_data = CreateGradientBuffer(colors_, stops_);
if (gradient_data.texture_size > FIXED_GRADIENT_SIZE) {
return RenderTexture(gradient_data, renderer, entity, pass);
}
return RenderFixed(gradient_data, renderer, entity, pass);
#endif // FML_OS_ANDROID
}

bool LinearGradientContents::RenderTexture(const GradientData& gradient_data,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = LinearGradientFillPipeline::VertexShader;
using FS = LinearGradientFillPipeline::FragmentShader;

auto gradient_texture =
CreateGradientTexture(colors_, stops_, renderer.GetContext());
CreateGradientTexture(gradient_data, renderer.GetContext());
if (gradient_texture == nullptr) {
return false;
}
Expand Down Expand Up @@ -106,4 +122,57 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
return true;
}

#ifndef FML_OS_ANDROID
bool LinearGradientContents::RenderFixed(const GradientData& gradient_data,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const {
using VS = LinearGradientFixedFillPipeline::VertexShader;
using FS = LinearGradientFixedFillPipeline::FragmentShader;

FS::GradientInfo gradient_info;
gradient_info.start_point = start_point_;
gradient_info.end_point = end_point_;
gradient_info.tile_mode = static_cast<Scalar>(tile_mode_);
gradient_info.alpha = GetAlpha();
gradient_info.colors_length = gradient_data.texture_size;
for (auto i = 0u; i < gradient_data.colors.size(); i++) {
gradient_info.colors[i] = gradient_data.colors[i];
}

VS::FrameInfo frame_info;
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
entity.GetTransformation();
frame_info.matrix = GetInverseMatrix();

Command cmd;
cmd.label = "LinearGradientFixedFill";
cmd.stencil_reference = entity.GetStencilDepth();

auto geometry_result =
GetGeometry()->GetPositionBuffer(renderer, entity, pass);
auto options = OptionsFromPassAndEntity(pass, entity);
if (geometry_result.prevent_overdraw) {
options.stencil_compare = CompareFunction::kEqual;
options.stencil_operation = StencilOperation::kIncrementClamp;
}
options.primitive_type = geometry_result.type;
cmd.pipeline = renderer.GetLinearGradientFixedFillPipeline(options);

cmd.BindVertices(geometry_result.vertex_buffer);
FS::BindGradientInfo(
cmd, pass.GetTransientsBuffer().EmplaceUniform(gradient_info));
VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));

if (!pass.AddCommand(std::move(cmd))) {
return false;
}

if (geometry_result.prevent_overdraw) {
return ClipRestoreContents().Render(renderer, entity, pass);
}
return true;
}
#endif // FML_OS_ANDROID

} // namespace impeller
13 changes: 13 additions & 0 deletions impeller/entity/contents/linear_gradient_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "impeller/entity/contents/color_source_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/gradient.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/point.h"

Expand Down Expand Up @@ -42,6 +43,18 @@ class LinearGradientContents final : public ColorSourceContents {
void SetTileMode(Entity::TileMode tile_mode);

private:
bool RenderTexture(const GradientData& gradient_data,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const;

#ifndef FML_OS_ANDROID
bool RenderFixed(const GradientData& gradient_data,
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const;
#endif // FML_OS_ANDROID

Point start_point_;
Point end_point_;
std::vector<Color> colors_;
Expand Down
Loading