Skip to content

Commit

Permalink
[Impeller] made plus an advanced blend
Browse files Browse the repository at this point in the history
  • Loading branch information
gaaclarke committed Mar 21, 2024
1 parent 4069da3 commit 34112d7
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 18 deletions.
36 changes: 36 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,42 @@ TEST_P(AiksTest, BlendModePlusAlpha) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

// Bug: https://github.com/flutter/flutter/issues/142549
TEST_P(AiksTest, BlendModePlusAlphaHalf) {
Canvas canvas;
canvas.Scale(GetContentScale());
canvas.DrawPaint({.color = Color(0.9, 1.0, 0.9, 1.0)});
canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
{.color = Color(1, 0, 0, 0.5)});
canvas.SaveLayer({});
Paint paint;
paint.blend_mode = BlendMode::kPlus;
paint.color = Color(0, 0, 1, 0.5);
canvas.DrawRect(Rect::MakeXYWH(0, 0, 150, 300), paint);
paint.color = Color(1, 0, 1, 1);
canvas.DrawRect(Rect::MakeXYWH(150, 0, 150, 300), paint);
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, BlendModePlusAlphaFoo) {
Canvas canvas;
canvas.Scale(GetContentScale());
canvas.DrawPaint({.color = Color(0.9, 1.0, 0.9, 1.0)});
canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300), {.color = Color(1, 0, 0, 1)});
canvas.SaveLayer({});
Paint paint;
paint.blend_mode = BlendMode::kPlus;
paint.color = Color(0, 0, 1, 10.0 / 255.0);
for (int i = 0; i < 20; ++i) {
canvas.DrawRect(Rect::MakeXYWH(0, 0, 150, 300), paint);
}
paint.color = Color(0, 0, 1, 200.0 / 255.0);
canvas.DrawRect(Rect::MakeXYWH(150, 0, 150, 300), paint);
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, ColorWheel) {
// Compare with https://fiddle.skia.org/c/@BlendModes

Expand Down
15 changes: 6 additions & 9 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,6 @@ void ContentContextOptions::ApplyToPipelineDescriptor(
color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
break;
case BlendMode::kPlus:
color0.dst_alpha_blend_factor =
IsAlphaClampedToOne(color_attachment_pixel_format)
? BlendFactor::kOne
: BlendFactor::kOneMinusSourceAlpha;
color0.dst_color_blend_factor = BlendFactor::kOne;
color0.src_alpha_blend_factor = BlendFactor::kOne;
color0.src_color_blend_factor = BlendFactor::kOne;
break;
case BlendMode::kModulate:
color0.dst_alpha_blend_factor = BlendFactor::kSourceAlpha;
color0.dst_color_blend_factor = BlendFactor::kSourceColor;
Expand Down Expand Up @@ -332,6 +323,9 @@ ContentContext::ContentContext(
framebuffer_blend_lighten_pipelines_.CreateDefault(
*context_, options_trianglestrip,
{static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
framebuffer_blend_plus_pipelines_.CreateDefault(
*context_, options_trianglestrip,
{static_cast<Scalar>(BlendSelectValues::kPlus), supports_decal});
framebuffer_blend_luminosity_pipelines_.CreateDefault(
*context_, options_trianglestrip,
{static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
Expand Down Expand Up @@ -379,6 +373,9 @@ ContentContext::ContentContext(
blend_lighten_pipelines_.CreateDefault(
*context_, options_trianglestrip,
{static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
blend_plus_pipelines_.CreateDefault(
*context_, options_trianglestrip,
{static_cast<Scalar>(BlendSelectValues::kPlus), supports_decal});
blend_luminosity_pipelines_.CreateDefault(
*context_, options_trianglestrip,
{static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
Expand Down
19 changes: 19 additions & 0 deletions impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ using BlendHuePipeline =
RenderPipelineT<AdvancedBlendVertexShader, AdvancedBlendFragmentShader>;
using BlendLightenPipeline =
RenderPipelineT<AdvancedBlendVertexShader, AdvancedBlendFragmentShader>;
using BlendPlusPipeline =
RenderPipelineT<AdvancedBlendVertexShader, AdvancedBlendFragmentShader>;
using BlendLuminosityPipeline =
RenderPipelineT<AdvancedBlendVertexShader, AdvancedBlendFragmentShader>;
using BlendMultiplyPipeline =
Expand Down Expand Up @@ -237,6 +239,9 @@ using FramebufferBlendHuePipeline =
using FramebufferBlendLightenPipeline =
RenderPipelineT<FramebufferBlendVertexShader,
FramebufferBlendFragmentShader>;
using FramebufferBlendPlusPipeline =
RenderPipelineT<FramebufferBlendVertexShader,
FramebufferBlendFragmentShader>;
using FramebufferBlendLuminosityPipeline =
RenderPipelineT<FramebufferBlendVertexShader,
FramebufferBlendFragmentShader>;
Expand Down Expand Up @@ -640,6 +645,11 @@ class ContentContext {
return GetPipeline(blend_lighten_pipelines_, opts);
}

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

std::shared_ptr<Pipeline<PipelineDescriptor>> GetBlendLuminosityPipeline(
ContentContextOptions opts) const {
return GetPipeline(blend_luminosity_pipelines_, opts);
Expand Down Expand Up @@ -725,6 +735,12 @@ class ContentContext {
return GetPipeline(framebuffer_blend_lighten_pipelines_, opts);
}

std::shared_ptr<Pipeline<PipelineDescriptor>> GetFramebufferBlendPlusPipeline(
ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
return GetPipeline(framebuffer_blend_plus_pipelines_, opts);
}

std::shared_ptr<Pipeline<PipelineDescriptor>>
GetFramebufferBlendLuminosityPipeline(ContentContextOptions opts) const {
FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch());
Expand Down Expand Up @@ -993,6 +1009,7 @@ class ContentContext {
mutable Variants<BlendHardLightPipeline> blend_hardlight_pipelines_;
mutable Variants<BlendHuePipeline> blend_hue_pipelines_;
mutable Variants<BlendLightenPipeline> blend_lighten_pipelines_;
mutable Variants<BlendPlusPipeline> blend_plus_pipelines_;
mutable Variants<BlendLuminosityPipeline> blend_luminosity_pipelines_;
mutable Variants<BlendMultiplyPipeline> blend_multiply_pipelines_;
mutable Variants<BlendOverlayPipeline> blend_overlay_pipelines_;
Expand All @@ -1018,6 +1035,8 @@ class ContentContext {
framebuffer_blend_hue_pipelines_;
mutable Variants<FramebufferBlendLightenPipeline>
framebuffer_blend_lighten_pipelines_;
mutable Variants<FramebufferBlendPlusPipeline>
framebuffer_blend_plus_pipelines_;
mutable Variants<FramebufferBlendLuminosityPipeline>
framebuffer_blend_luminosity_pipelines_;
mutable Variants<FramebufferBlendMultiplyPipeline>
Expand Down
3 changes: 3 additions & 0 deletions impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
case BlendMode::kColor:
pass.SetPipeline(renderer.GetBlendColorPipeline(options));
break;
case BlendMode::kPlus:
pass.SetPipeline(renderer.GetBlendPlusPipeline(options));
break;
case BlendMode::kLuminosity:
pass.SetPipeline(renderer.GetBlendLuminosityPipeline(options));
break;
Expand Down
3 changes: 1 addition & 2 deletions impeller/entity/contents/filters/blend_filter_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

namespace impeller {

constexpr std::array<std::array<Scalar, 5>, 15> kPorterDuffCoefficients = {{
constexpr std::array<std::array<Scalar, 5>, 14> kPorterDuffCoefficients = {{
{0, 0, 0, 0, 0}, // Clear
{1, 0, 0, 0, 0}, // Source
{0, 0, 1, 0, 0}, // Destination
Expand All @@ -25,7 +25,6 @@ constexpr std::array<std::array<Scalar, 5>, 15> kPorterDuffCoefficients = {{
{0, 1, 1, -1, 0}, // SourceATop
{1, -1, 0, 1, 0}, // DestinationATop
{1, -1, 1, -1, 0}, // Xor
{1, 0, 1, 0, 0}, // Plus
{0, 0, 0, 0, 1}, // Modulate
{0, 0, 1, 0, -1}, // Screen
}};
Expand Down
3 changes: 3 additions & 0 deletions impeller/entity/contents/framebuffer_blend_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer,
case BlendMode::kColor:
pass.SetPipeline(renderer.GetFramebufferBlendColorPipeline(options));
break;
case BlendMode::kPlus:
pass.SetPipeline(renderer.GetFramebufferBlendPlusPipeline(options));
break;
case BlendMode::kLuminosity:
pass.SetPipeline(renderer.GetFramebufferBlendLuminosityPipeline(options));
break;
Expand Down
1 change: 1 addition & 0 deletions impeller/entity/contents/framebuffer_blend_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum class BlendSelectValues {
kHue,
kSaturation,
kColor,
kPlus,
kLuminosity,
};

Expand Down
13 changes: 11 additions & 2 deletions impeller/entity/shaders/blending/advanced_blend.frag
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,16 @@ void main() {
src.a *= blend_info.src_input_alpha;
}

f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, int(blend_type));
int nblend_type = int(blend_type);

frag_color = IPApplyBlendedColor(dst, src, blend_result);
if (nblend_type == /*BlendSelectValues::kPlus*/ 14) {
f16vec4 plus = src + dst;
if (plus.a > 1.0hf) {
plus.a = 1.0hf;
}
frag_color = IPHalfPremultiply(plus);
} else {
f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, nblend_type);
frag_color = IPApplyBlendedColor(dst, src, blend_result);
}
}
4 changes: 3 additions & 1 deletion impeller/entity/shaders/blending/blend_select.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// kHue,
// kSaturation,
// kColor,
// kPlus,
// kLuminosity,
// Note, this isn't a switch as GLSL ES 1.0 does not support them.
f16vec3 AdvancedBlend(f16vec3 dst, f16vec3 src, int blend_type) {
Expand Down Expand Up @@ -65,7 +66,8 @@ f16vec3 AdvancedBlend(f16vec3 dst, f16vec3 src, int blend_type) {
if (blend_type == 13) {
return IPBlendColor(dst, src);
}
if (blend_type == 14) {
// 14 is `plus`, it's handled in advanced_blend.frag.
if (blend_type == 15) {
return IPBlendLuminosity(dst, src);
}
return f16vec3(0.0hf);
Expand Down
13 changes: 11 additions & 2 deletions impeller/entity/shaders/blending/framebuffer_blend.frag
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,16 @@ void main() {
)));
src.a *= frag_info.src_input_alpha;

f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, int(blend_type));
int nblend_type = int(blend_type);

frag_color = IPApplyBlendedColor(dst, src, blend_result);
if (nblend_type == /*BlendSelectValues::kPlus*/ 14) {
f16vec4 plus = src + dst;
if (plus.a > 1.0hf) {
plus.a = 1.0hf;
}
frag_color = IPHalfPremultiply(plus);
} else {
f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, nblend_type);
frag_color = IPApplyBlendedColor(dst, src, blend_result);
}
}
4 changes: 2 additions & 2 deletions impeller/geometry/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
V(SourceATop) \
V(DestinationATop) \
V(Xor) \
V(Plus) \
V(Modulate) \
V(Screen) \
V(Overlay) \
Expand All @@ -45,6 +44,7 @@
V(Hue) \
V(Saturation) \
V(Color) \
V(Plus) \
V(Luminosity)

namespace impeller {
Expand All @@ -71,7 +71,6 @@ enum class BlendMode : uint8_t {
kSourceATop,
kDestinationATop,
kXor,
kPlus,
kModulate,

// The following blend modes use equations that are not available for
Expand All @@ -91,6 +90,7 @@ enum class BlendMode : uint8_t {
kHue,
kSaturation,
kColor,
kPlus,
kLuminosity,

kLast = kLuminosity,
Expand Down

0 comments on commit 34112d7

Please sign in to comment.