Skip to content

Commit

Permalink
[Impeller] Will it blend? (flutter#33817)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero authored Jun 4, 2022
1 parent a48d5c5 commit 356618c
Show file tree
Hide file tree
Showing 20 changed files with 332 additions and 46 deletions.
10 changes: 10 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,17 @@ FILE: ../../../flutter/impeller/entity/entity_unittests.cc
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_colorburn.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_colordodge.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_darken.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_difference.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_exclusion.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_hardlight.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_lighten.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_multiply.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_overlay.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_screen.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_softlight.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_utils.glsl
FILE: ../../../flutter/impeller/entity/shaders/blending/blend.frag
FILE: ../../../flutter/impeller/entity/shaders/blending/blend.vert
FILE: ../../../flutter/impeller/entity/shaders/border_mask_blur.frag
Expand Down
9 changes: 9 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,16 @@ TEST_P(AiksTest, ColorWheel) {
{"Modulate", Entity::BlendMode::kModulate},
// Advanced blends (color component blends)
{"Screen", Entity::BlendMode::kScreen},
{"Overlay", Entity::BlendMode::kOverlay},
{"Darken", Entity::BlendMode::kDarken},
{"Lighten", Entity::BlendMode::kLighten},
{"ColorDodge", Entity::BlendMode::kColorDodge},
{"ColorBurn", Entity::BlendMode::kColorBurn},
{"HardLight", Entity::BlendMode::kHardLight},
{"SoftLight", Entity::BlendMode::kSoftLight},
{"Difference", Entity::BlendMode::kDifference},
{"Exclusion", Entity::BlendMode::kExclusion},
{"Multiply", Entity::BlendMode::kMultiply},
};
assert(blends.size() ==
static_cast<size_t>(Entity::BlendMode::kLastAdvancedBlendMode) + 1);
Expand Down
13 changes: 11 additions & 2 deletions impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,26 @@ static std::optional<Entity::BlendMode> ToBlendMode(flutter::DlBlendMode mode) {
return Entity::BlendMode::kModulate;
case flutter::DlBlendMode::kScreen:
return Entity::BlendMode::kScreen;
case flutter::DlBlendMode::kColorBurn:
return Entity::BlendMode::kColorBurn;
case flutter::DlBlendMode::kOverlay:
return Entity::BlendMode::kOverlay;
case flutter::DlBlendMode::kDarken:
return Entity::BlendMode::kDarken;
case flutter::DlBlendMode::kLighten:
return Entity::BlendMode::kLighten;
case flutter::DlBlendMode::kColorDodge:
return Entity::BlendMode::kColorDodge;
case flutter::DlBlendMode::kColorBurn:
return Entity::BlendMode::kColorBurn;
case flutter::DlBlendMode::kHardLight:
return Entity::BlendMode::kHardLight;
case flutter::DlBlendMode::kSoftLight:
return Entity::BlendMode::kSoftLight;
case flutter::DlBlendMode::kDifference:
return Entity::BlendMode::kDifference;
case flutter::DlBlendMode::kExclusion:
return Entity::BlendMode::kExclusion;
case flutter::DlBlendMode::kMultiply:
return Entity::BlendMode::kMultiply;
case flutter::DlBlendMode::kHue:
case flutter::DlBlendMode::kSaturation:
case flutter::DlBlendMode::kColor:
Expand Down
9 changes: 9 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ impeller_shaders("entity_shaders") {
shaders = [
"shaders/blending/advanced_blend.vert",
"shaders/blending/advanced_blend_colorburn.frag",
"shaders/blending/advanced_blend_colordodge.frag",
"shaders/blending/advanced_blend_darken.frag",
"shaders/blending/advanced_blend_difference.frag",
"shaders/blending/advanced_blend_exclusion.frag",
"shaders/blending/advanced_blend_hardlight.frag",
"shaders/blending/advanced_blend_lighten.frag",
"shaders/blending/advanced_blend_multiply.frag",
"shaders/blending/advanced_blend_overlay.frag",
"shaders/blending/advanced_blend_screen.frag",
"shaders/blending/advanced_blend_softlight.frag",
"shaders/blending/blend.frag",
"shaders/blending/blend.vert",
"shaders/border_mask_blur.frag",
Expand Down
22 changes: 20 additions & 2 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,28 @@ ContentContext::ContentContext(std::shared_ptr<Context> context)
CreateDefaultPipeline<SolidFillPipeline>(*context_);
texture_blend_pipelines_[{}] =
CreateDefaultPipeline<BlendPipeline>(*context_);
blend_colorburn_pipelines_[{}] =
CreateDefaultPipeline<BlendColorBurnPipeline>(*context_);
blend_colordodge_pipelines_[{}] =
CreateDefaultPipeline<BlendColorDodgePipeline>(*context_);
blend_darken_pipelines_[{}] =
CreateDefaultPipeline<BlendDarkenPipeline>(*context_);
blend_difference_pipelines_[{}] =
CreateDefaultPipeline<BlendDifferencePipeline>(*context_);
blend_exclusion_pipelines_[{}] =
CreateDefaultPipeline<BlendExclusionPipeline>(*context_);
blend_hardlight_pipelines_[{}] =
CreateDefaultPipeline<BlendHardLightPipeline>(*context_);
blend_lighten_pipelines_[{}] =
CreateDefaultPipeline<BlendLightenPipeline>(*context_);
blend_multiply_pipelines_[{}] =
CreateDefaultPipeline<BlendMultiplyPipeline>(*context_);
blend_overlay_pipelines_[{}] =
CreateDefaultPipeline<BlendOverlayPipeline>(*context_);
blend_screen_pipelines_[{}] =
CreateDefaultPipeline<BlendScreenPipeline>(*context_);
blend_colorburn_pipelines_[{}] =
CreateDefaultPipeline<BlendColorburnPipeline>(*context_);
blend_softlight_pipelines_[{}] =
CreateDefaultPipeline<BlendSoftLightPipeline>(*context_);
texture_pipelines_[{}] = CreateDefaultPipeline<TexturePipeline>(*context_);
gaussian_blur_pipelines_[{}] =
CreateDefaultPipeline<GaussianBlurPipeline>(*context_);
Expand Down
112 changes: 98 additions & 14 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@
#include "impeller/base/validation.h"
#include "impeller/entity/advanced_blend.vert.h"
#include "impeller/entity/advanced_blend_colorburn.frag.h"
#include "impeller/entity/advanced_blend_colordodge.frag.h"
#include "impeller/entity/advanced_blend_darken.frag.h"
#include "impeller/entity/advanced_blend_difference.frag.h"
#include "impeller/entity/advanced_blend_exclusion.frag.h"
#include "impeller/entity/advanced_blend_hardlight.frag.h"
#include "impeller/entity/advanced_blend_lighten.frag.h"
#include "impeller/entity/advanced_blend_multiply.frag.h"
#include "impeller/entity/advanced_blend_overlay.frag.h"
#include "impeller/entity/advanced_blend_screen.frag.h"
#include "impeller/entity/advanced_blend_softlight.frag.h"
#include "impeller/entity/blend.frag.h"
#include "impeller/entity/blend.vert.h"
#include "impeller/entity/border_mask_blur.frag.h"
Expand Down Expand Up @@ -42,10 +51,28 @@ using GradientFillPipeline =
using SolidFillPipeline =
PipelineT<SolidFillVertexShader, SolidFillFragmentShader>;
using BlendPipeline = PipelineT<BlendVertexShader, BlendFragmentShader>;
using BlendColorBurnPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendColorburnFragmentShader>;
using BlendColorDodgePipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendColordodgeFragmentShader>;
using BlendDarkenPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendDarkenFragmentShader>;
using BlendDifferencePipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendDifferenceFragmentShader>;
using BlendExclusionPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendExclusionFragmentShader>;
using BlendHardLightPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendHardlightFragmentShader>;
using BlendLightenPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendLightenFragmentShader>;
using BlendMultiplyPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendMultiplyFragmentShader>;
using BlendOverlayPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendOverlayFragmentShader>;
using BlendScreenPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendScreenFragmentShader>;
using BlendColorburnPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendColorburnFragmentShader>;
using BlendSoftLightPipeline =
PipelineT<AdvancedBlendVertexShader, AdvancedBlendSoftlightFragmentShader>;
using TexturePipeline =
PipelineT<TextureFillVertexShader, TextureFillFragmentShader>;
using GaussianBlurPipeline =
Expand Down Expand Up @@ -110,16 +137,6 @@ class ContentContext {
return GetPipeline(texture_blend_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendScreenPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_screen_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendColorburnPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_colorburn_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetTexturePipeline(
ContentContextOptions opts) const {
return GetPipeline(texture_pipelines_, opts);
Expand Down Expand Up @@ -154,6 +171,63 @@ class ContentContext {
return GetPipeline(vertices_pipelines_, opts);
}

// Advanced blends.

std::shared_ptr<Pipeline> GetBlendColorBurnPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_colorburn_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendColorDodgePipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_colordodge_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendDarkenPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_darken_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendDifferencePipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_difference_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendExclusionPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_exclusion_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendHardLightPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_hardlight_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendLightenPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_lighten_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendMultiplyPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_multiply_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendOverlayPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_overlay_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendScreenPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_screen_pipelines_, opts);
}

std::shared_ptr<Pipeline> GetBlendSoftLightPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_softlight_pipelines_, opts);
}

std::shared_ptr<Context> GetContext() const;

using SubpassCallback =
Expand All @@ -179,15 +253,25 @@ class ContentContext {
mutable Variants<GradientFillPipeline> gradient_fill_pipelines_;
mutable Variants<SolidFillPipeline> solid_fill_pipelines_;
mutable Variants<BlendPipeline> texture_blend_pipelines_;
mutable Variants<BlendScreenPipeline> blend_screen_pipelines_;
mutable Variants<BlendColorburnPipeline> blend_colorburn_pipelines_;
mutable Variants<TexturePipeline> texture_pipelines_;
mutable Variants<GaussianBlurPipeline> gaussian_blur_pipelines_;
mutable Variants<BorderMaskBlurPipeline> border_mask_blur_pipelines_;
mutable Variants<SolidStrokePipeline> solid_stroke_pipelines_;
mutable Variants<ClipPipeline> clip_pipelines_;
mutable Variants<GlyphAtlasPipeline> glyph_atlas_pipelines_;
mutable Variants<VerticesPipeline> vertices_pipelines_;
// Advanced blends.
mutable Variants<BlendColorBurnPipeline> blend_colorburn_pipelines_;
mutable Variants<BlendColorDodgePipeline> blend_colordodge_pipelines_;
mutable Variants<BlendDarkenPipeline> blend_darken_pipelines_;
mutable Variants<BlendDifferencePipeline> blend_difference_pipelines_;
mutable Variants<BlendExclusionPipeline> blend_exclusion_pipelines_;
mutable Variants<BlendHardLightPipeline> blend_hardlight_pipelines_;
mutable Variants<BlendLightenPipeline> blend_lighten_pipelines_;
mutable Variants<BlendMultiplyPipeline> blend_multiply_pipelines_;
mutable Variants<BlendOverlayPipeline> blend_overlay_pipelines_;
mutable Variants<BlendScreenPipeline> blend_screen_pipelines_;
mutable Variants<BlendSoftLightPipeline> blend_softlight_pipelines_;

template <class TypedPipeline>
std::shared_ptr<Pipeline> GetPipeline(Variants<TypedPipeline>& container,
Expand Down
47 changes: 24 additions & 23 deletions impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,18 @@ static bool PipelineBlend(const FilterInput::Vector& inputs,
return true;
}

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

void BlendFilterContents::SetBlendMode(Entity::BlendMode blend_mode) {
if (blend_mode > Entity::BlendMode::kLastAdvancedBlendMode) {
VALIDATION_LOG << "Invalid blend mode " << static_cast<int>(blend_mode)
Expand All @@ -226,31 +238,20 @@ void BlendFilterContents::SetBlendMode(Entity::BlendMode blend_mode) {

if (blend_mode > Entity::BlendMode::kLastPipelineBlendMode) {
static_assert(Entity::BlendMode::kLastAdvancedBlendMode ==
Entity::BlendMode::kColorBurn);
Entity::BlendMode::kMultiply);

switch (blend_mode) {
case Entity::BlendMode::kScreen:
advanced_blend_proc_ = [](const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity, RenderPass& pass,
const Rect& coverage,
std::optional<Color> fg_color) {
PipelineProc p = &ContentContext::GetBlendScreenPipeline;
return AdvancedBlend<BlendScreenPipeline>(
inputs, renderer, entity, pass, coverage, fg_color, p);
};
break;
case Entity::BlendMode::kColorBurn:
advanced_blend_proc_ = [](const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity, RenderPass& pass,
const Rect& coverage,
std::optional<Color> fg_color) {
PipelineProc p = &ContentContext::GetBlendColorburnPipeline;
return AdvancedBlend<BlendColorburnPipeline>(
inputs, renderer, entity, pass, coverage, fg_color, p);
};
break;
BLEND_CASE(Screen)
BLEND_CASE(Overlay)
BLEND_CASE(Darken)
BLEND_CASE(Lighten)
BLEND_CASE(ColorDodge)
BLEND_CASE(ColorBurn)
BLEND_CASE(HardLight)
BLEND_CASE(SoftLight)
BLEND_CASE(Difference)
BLEND_CASE(Exclusion)
BLEND_CASE(Multiply)
default:
FML_UNREACHABLE();
}
Expand Down
11 changes: 10 additions & 1 deletion impeller/entity/entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,19 @@ class Entity {
// pipelines on most graphics devices without extensions, and so they are
// only able to be used via `BlendFilterContents`.
kScreen,
kOverlay,
kDarken,
kLighten,
kColorDodge,
kColorBurn,
kHardLight,
kSoftLight,
kDifference,
kExclusion,
kMultiply,

kLastPipelineBlendMode = kModulate,
kLastAdvancedBlendMode = kColorBurn,
kLastAdvancedBlendMode = kMultiply,
};

enum class ClipOperation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

vec3 ComponentIsValue(vec3 n, float value) {
return vec3(n.r == value, n.g == value, n.b == value);
}
#include "advanced_blend_utils.glsl"

vec3 Blend(vec3 dst, vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingcolorburn
vec3 color = 1 - min(vec3(1), (1 - dst) / src);
color = mix(color, vec3(1), ComponentIsValue(dst, 1.0));
color = mix(color, vec3(0), ComponentIsValue(src, 0.0));
Expand Down
15 changes: 15 additions & 0 deletions impeller/entity/shaders/blending/advanced_blend_colordodge.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 "advanced_blend_utils.glsl"

vec3 Blend(vec3 dst, vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingcolordodge
vec3 color = min(vec3(1), dst / (1 - src));
color = mix(color, vec3(0), ComponentIsValue(dst, 0.0));
color = mix(color, vec3(1), ComponentIsValue(src, 1.0));
return color;
}

#include "advanced_blend.glsl"
10 changes: 10 additions & 0 deletions impeller/entity/shaders/blending/advanced_blend_darken.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// 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.

vec3 Blend(vec3 dst, vec3 src) {
// https://www.w3.org/TR/compositing-1/#blendingdarken
return min(dst, src);
}

#include "advanced_blend.glsl"
Loading

0 comments on commit 356618c

Please sign in to comment.