Skip to content

Commit

Permalink
[Impeller] fixes PlusAdvanced alpha blending / adds alpha blending te…
Browse files Browse the repository at this point in the history
…sts (flutter#51787)

flutter#51756 had a bug in it when src
alpha was not 1. There was no test coverage for this. I've added the fix
and test coverage for all the blends.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I added new tests to check the change I am making or feature I am
adding, or the PR is [test-exempt]. See [testing the engine] for
instructions on writing and running engine tests.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I signed the [CLA].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
  • Loading branch information
gaaclarke authored Apr 2, 2024
1 parent bb4ec2d commit ef60a95
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 12 deletions.
56 changes: 44 additions & 12 deletions impeller/aiks/aiks_blend_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,14 @@ TEST_P(AiksTest, ClearBlend) {
static Picture BlendModeTest(Vector2 content_scale,
BlendMode blend_mode,
const std::shared_ptr<Image>& src_image,
const std::shared_ptr<Image>& dst_image) {
const std::shared_ptr<Image>& dst_image,
Scalar src_alpha) {
if (AiksTest::ImGuiBegin("Controls", nullptr,
ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
ImGui::End();
}

Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
Color::LimeGreen().WithAlpha(0.75),
Expand Down Expand Up @@ -456,8 +463,15 @@ static Picture BlendModeTest(Vector2 content_scale,
canvas.Save();
canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
{
canvas.DrawImage(dst_image, {0, 0}, {.blend_mode = BlendMode::kSourceOver});
canvas.DrawImage(src_image, {0, 0}, {.blend_mode = blend_mode});
canvas.DrawImage(dst_image, {0, 0},
{
.blend_mode = BlendMode::kSourceOver,
});
canvas.DrawImage(src_image, {0, 0},
{
.color = Color::White().WithAlpha(src_alpha),
.blend_mode = blend_mode,
});
}
canvas.Restore();
canvas.Restore();
Expand All @@ -468,7 +482,8 @@ static Picture BlendModeTest(Vector2 content_scale,
{
canvas.DrawImage(dst_image, {400, 0},
{.blend_mode = BlendMode::kSourceOver});
canvas.SaveLayer({.blend_mode = blend_mode});
canvas.SaveLayer({.color = Color::White().WithAlpha(src_alpha),
.blend_mode = blend_mode});
{
canvas.DrawImage(src_image, {400, 0},
{.blend_mode = BlendMode::kSourceOver});
Expand All @@ -481,17 +496,34 @@ static Picture BlendModeTest(Vector2 content_scale,
return canvas.EndRecordingAsPicture();
}

#define BLEND_MODE_TEST(blend_mode) \
TEST_P(AiksTest, BlendMode##blend_mode) { \
auto src_image = std::make_shared<Image>( \
CreateTextureForFixture("blend_mode_src.png")); \
auto dst_image = std::make_shared<Image>( \
CreateTextureForFixture("blend_mode_dst.png")); \
OpenPlaygroundHere(BlendModeTest( \
GetContentScale(), BlendMode::k##blend_mode, src_image, dst_image)); \
#define BLEND_MODE_TEST(blend_mode) \
TEST_P(AiksTest, BlendMode##blend_mode) { \
auto src_image = std::make_shared<Image>( \
CreateTextureForFixture("blend_mode_src.png")); \
auto dst_image = std::make_shared<Image>( \
CreateTextureForFixture("blend_mode_dst.png")); \
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> { \
return BlendModeTest(GetContentScale(), BlendMode::k##blend_mode, \
src_image, dst_image, /*src_alpha=*/1.0); \
}; \
OpenPlaygroundHere(callback); \
}
IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TEST)

#define BLEND_MODE_SRC_ALPHA_TEST(blend_mode) \
TEST_P(AiksTest, BlendModeSrcAlpha##blend_mode) { \
auto src_image = std::make_shared<Image>( \
CreateTextureForFixture("blend_mode_src.png")); \
auto dst_image = std::make_shared<Image>( \
CreateTextureForFixture("blend_mode_dst.png")); \
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> { \
return BlendModeTest(GetContentScale(), BlendMode::k##blend_mode, \
src_image, dst_image, /*src_alpha=*/0.5); \
}; \
OpenPlaygroundHere(callback); \
}
IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_SRC_ALPHA_TEST)

TEST_P(AiksTest, CanDrawPaintMultipleTimesInteractive) {
auto modes = GetBlendModeSelection();

Expand Down
1 change: 1 addition & 0 deletions impeller/entity/shaders/blending/framebuffer_blend.frag
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void main() {
int nblend_type = int(blend_type);

if (nblend_type == /*BlendSelectValues::kPlusAdvanced*/ 14) {
premultiplied_src *= frag_info.src_input_alpha;
frag_color = IPHalfPlusBlend(premultiplied_src, premultiplied_dst);
} else {
f16vec4 dst = IPHalfUnpremultiply(premultiplied_dst);
Expand Down
90 changes: 90 additions & 0 deletions testing/impeller_golden_tests_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,96 @@ impeller_Play_AiksTest_BlendModeSourceOver_Vulkan.png
impeller_Play_AiksTest_BlendModeSource_Metal.png
impeller_Play_AiksTest_BlendModeSource_OpenGLES.png
impeller_Play_AiksTest_BlendModeSource_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaClear_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaClear_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaClear_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaColorBurn_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaColorBurn_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaColorBurn_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaColorDodge_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaColorDodge_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaColorDodge_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaColor_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaColor_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaColor_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDarken_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDarken_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDarken_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationATop_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationATop_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationATop_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationIn_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationIn_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationIn_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationOut_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationOut_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationOut_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationOver_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationOver_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestinationOver_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestination_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestination_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDestination_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaDifference_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaDifference_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaDifference_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaExclusion_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaExclusion_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaExclusion_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaHardLight_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaHardLight_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaHardLight_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaHue_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaHue_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaHue_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaLighten_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaLighten_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaLighten_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaLuminosity_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaLuminosity_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaLuminosity_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaModulate_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaModulate_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaModulate_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaMultiply_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaMultiply_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaMultiply_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaOverlay_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaOverlay_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaOverlay_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaPlusAdvanced_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaPlusAdvanced_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaPlusAdvanced_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaPlus_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaPlus_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaPlus_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSaturation_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSaturation_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSaturation_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaScreen_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaScreen_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaScreen_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSoftLight_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSoftLight_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSoftLight_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceATop_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceATop_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceATop_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceIn_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceIn_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceIn_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceOut_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceOut_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceOut_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceOver_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceOver_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSourceOver_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaSource_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaSource_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaSource_Vulkan.png
impeller_Play_AiksTest_BlendModeSrcAlphaXor_Metal.png
impeller_Play_AiksTest_BlendModeSrcAlphaXor_OpenGLES.png
impeller_Play_AiksTest_BlendModeSrcAlphaXor_Vulkan.png
impeller_Play_AiksTest_BlendModeXor_Metal.png
impeller_Play_AiksTest_BlendModeXor_OpenGLES.png
impeller_Play_AiksTest_BlendModeXor_Vulkan.png
Expand Down

0 comments on commit ef60a95

Please sign in to comment.