diff --git a/display_list/testing/dl_test_surface_metal.cc b/display_list/testing/dl_test_surface_metal.cc index b7d7f7047bd41..def57908b4671 100644 --- a/display_list/testing/dl_test_surface_metal.cc +++ b/display_list/testing/dl_test_surface_metal.cc @@ -115,7 +115,7 @@ sk_sp DlMetalSurfaceProvider::MakeImpellerImage( void DlMetalSurfaceProvider::InitScreenShotter() const { if (!snapshotter_) { - snapshotter_.reset(new MetalScreenshotter()); + snapshotter_.reset(new MetalScreenshotter(/*enable_wide_gamut=*/false)); auto typographer = impeller::TypographerContextSkia::Make(); aiks_context_.reset(new impeller::AiksContext( snapshotter_->GetPlayground().GetContext(), typographer)); diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 7dc1c2a5e31bf..c48a8bfc36206 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -1101,6 +1101,76 @@ TEST_P(AiksTest, PaintBlendModeIsRespected) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +// This makes sure the WideGamut named tests use 16bit float pixel format. +TEST_P(AiksTest, F16WideGamut) { + if (GetParam() != PlaygroundBackend::kMetal) { + GTEST_SKIP_("This backend doesn't yet support wide gamut."); + } + EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(), + PixelFormat::kR16G16B16A16Float); + EXPECT_FALSE(IsAlphaClampedToOne( + GetContext()->GetCapabilities()->GetDefaultColorFormat())); +} + +TEST_P(AiksTest, NotF16) { + EXPECT_TRUE(IsAlphaClampedToOne( + GetContext()->GetCapabilities()->GetDefaultColorFormat())); +} + +// Bug: https://github.com/flutter/flutter/issues/142549 +TEST_P(AiksTest, BlendModePlusAlphaWideGamut) { + if (GetParam() != PlaygroundBackend::kMetal) { + GTEST_SKIP_("This backend doesn't yet support wide gamut."); + } + EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(), + PixelFormat::kR16G16B16A16Float); + auto texture = CreateTextureForFixture("airplane.jpg", + /*enable_mipmapping=*/true); + + Canvas canvas; + canvas.Scale(GetContentScale()); + canvas.DrawPaint({.color = Color(0.9, 1.0, 0.9, 1.0)}); + canvas.SaveLayer({}); + Paint paint; + paint.blend_mode = BlendMode::kPlus; + paint.color = Color::Red(); + canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint); + paint.color = Color::White(); + canvas.DrawImageRect( + std::make_shared(texture), Rect::MakeSize(texture->GetSize()), + Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100), paint); + canvas.Restore(); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + +// Bug: https://github.com/flutter/flutter/issues/142549 +TEST_P(AiksTest, BlendModePlusAlphaColorFilterWideGamut) { + if (GetParam() != PlaygroundBackend::kMetal) { + GTEST_SKIP_("This backend doesn't yet support wide gamut."); + } + EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(), + PixelFormat::kR16G16B16A16Float); + auto texture = CreateTextureForFixture("airplane.jpg", + /*enable_mipmapping=*/true); + + Canvas canvas; + canvas.Scale(GetContentScale()); + canvas.DrawPaint({.color = Color(0.1, 0.2, 0.1, 1.0)}); + canvas.SaveLayer({ + .color_filter = + ColorFilter::MakeBlend(BlendMode::kPlus, Color(Vector4{1, 0, 0, 1})), + }); + Paint paint; + paint.color = Color::Red(); + canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint); + paint.color = Color::White(); + canvas.DrawImageRect( + std::make_shared(texture), Rect::MakeSize(texture->GetSize()), + Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100), paint); + canvas.Restore(); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + TEST_P(AiksTest, ColorWheel) { // Compare with https://fiddle.skia.org/c/@BlendModes diff --git a/impeller/compiler/shader_lib/impeller/color.glsl b/impeller/compiler/shader_lib/impeller/color.glsl index 310e22e779f76..c497f379fd550 100644 --- a/impeller/compiler/shader_lib/impeller/color.glsl +++ b/impeller/compiler/shader_lib/impeller/color.glsl @@ -46,4 +46,12 @@ f16vec4 IPHalfPremultiply(f16vec4 color) { return f16vec4(color.rgb * color.a, color.a); } +/// Performs the plus blend on `src` and `dst` which are premultiplied colors. +//`max` determines the values the results are clamped to. +f16vec4 IPHalfPlusBlend(f16vec4 src, f16vec4 dst) { + float16_t min = 0.0hf; + float16_t max = 1.0hf; + return clamp(dst + src, min, max); +} + #endif diff --git a/impeller/core/formats.h b/impeller/core/formats.h index aa859b45f6818..108cd454cd2fa 100644 --- a/impeller/core/formats.h +++ b/impeller/core/formats.h @@ -138,6 +138,14 @@ constexpr bool IsStencilWritable(PixelFormat format) { } } +/// Returns `true` if the pixel format has an implicit `clamp(x, 0, 1)` in the +/// pixel format. This is important for example when performing the `Plus` blend +/// where we don't want alpha values over 1.0. +constexpr bool IsAlphaClampedToOne(PixelFormat pixel_format) { + return !(pixel_format == PixelFormat::kR32G32B32A32Float || + pixel_format == PixelFormat::kR16G16B16A16Float); +} + constexpr const char* PixelFormatToString(PixelFormat format) { switch (format) { case PixelFormat::kUnknown: diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index f500d1b75c14c..f27096cd876d1 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -124,6 +124,8 @@ void ContentContextOptions::ApplyToPipelineDescriptor( color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha; break; case BlendMode::kPlus: + // The kPlusAdvanced should be used instead. + FML_DCHECK(IsAlphaClampedToOne(color_attachment_pixel_format)); color0.dst_alpha_blend_factor = BlendFactor::kOne; color0.dst_color_blend_factor = BlendFactor::kOne; color0.src_alpha_blend_factor = BlendFactor::kOne; @@ -324,6 +326,10 @@ ContentContext::ContentContext( framebuffer_blend_lighten_pipelines_.CreateDefault( *context_, options_trianglestrip, {static_cast(BlendSelectValues::kLighten), supports_decal}); + framebuffer_blend_plus_advanced_pipelines_.CreateDefault( + *context_, options_trianglestrip, + {static_cast(BlendSelectValues::kPlusAdvanced), + supports_decal}); framebuffer_blend_luminosity_pipelines_.CreateDefault( *context_, options_trianglestrip, {static_cast(BlendSelectValues::kLuminosity), supports_decal}); @@ -371,6 +377,9 @@ ContentContext::ContentContext( blend_lighten_pipelines_.CreateDefault( *context_, options_trianglestrip, {static_cast(BlendSelectValues::kLighten), supports_decal}); + blend_plus_advanced_pipelines_.CreateDefault( + *context_, options_trianglestrip, + {static_cast(BlendSelectValues::kPlusAdvanced), supports_decal}); blend_luminosity_pipelines_.CreateDefault( *context_, options_trianglestrip, {static_cast(BlendSelectValues::kLuminosity), supports_decal}); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index c1eed6ea2fada..5f0380a15461b 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -197,6 +197,8 @@ using BlendHuePipeline = RenderPipelineT; using BlendLightenPipeline = RenderPipelineT; +using BlendPlusAdvancedPipeline = + RenderPipelineT; using BlendLuminosityPipeline = RenderPipelineT; using BlendMultiplyPipeline = @@ -237,6 +239,9 @@ using FramebufferBlendHuePipeline = using FramebufferBlendLightenPipeline = RenderPipelineT; +using FramebufferBlendPlusAdvancedPipeline = + RenderPipelineT; using FramebufferBlendLuminosityPipeline = RenderPipelineT; @@ -640,6 +645,11 @@ class ContentContext { return GetPipeline(blend_lighten_pipelines_, opts); } + std::shared_ptr> GetBlendPlusAdvancedPipeline( + ContentContextOptions opts) const { + return GetPipeline(blend_plus_advanced_pipelines_, opts); + } + std::shared_ptr> GetBlendLuminosityPipeline( ContentContextOptions opts) const { return GetPipeline(blend_luminosity_pipelines_, opts); @@ -725,6 +735,12 @@ class ContentContext { return GetPipeline(framebuffer_blend_lighten_pipelines_, opts); } + std::shared_ptr> + GetFramebufferBlendPlusAdvancedPipeline(ContentContextOptions opts) const { + FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); + return GetPipeline(framebuffer_blend_plus_advanced_pipelines_, opts); + } + std::shared_ptr> GetFramebufferBlendLuminosityPipeline(ContentContextOptions opts) const { FML_DCHECK(GetDeviceCapabilities().SupportsFramebufferFetch()); @@ -989,6 +1005,7 @@ class ContentContext { mutable Variants blend_hardlight_pipelines_; mutable Variants blend_hue_pipelines_; mutable Variants blend_lighten_pipelines_; + mutable Variants blend_plus_advanced_pipelines_; mutable Variants blend_luminosity_pipelines_; mutable Variants blend_multiply_pipelines_; mutable Variants blend_overlay_pipelines_; @@ -1014,6 +1031,8 @@ class ContentContext { framebuffer_blend_hue_pipelines_; mutable Variants framebuffer_blend_lighten_pipelines_; + mutable Variants + framebuffer_blend_plus_advanced_pipelines_; mutable Variants framebuffer_blend_luminosity_pipelines_; mutable Variants diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index 4aadfa3f5ba8f..7941f9f7a9b6a 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -338,6 +338,9 @@ std::optional BlendFilterContents::CreateForegroundAdvancedBlend( case BlendMode::kColor: pass.SetPipeline(renderer.GetBlendColorPipeline(options)); break; + case BlendMode::kPlusAdvanced: + pass.SetPipeline(renderer.GetBlendPlusAdvancedPipeline(options)); + break; case BlendMode::kLuminosity: pass.SetPipeline(renderer.GetBlendLuminosityPipeline(options)); break; @@ -583,6 +586,7 @@ void BlendFilterContents::SetBlendMode(BlendMode blend_mode) { BLEND_CASE(Hue) BLEND_CASE(Saturation) BLEND_CASE(Color) + BLEND_CASE(PlusAdvanced) BLEND_CASE(Luminosity) default: FML_UNREACHABLE(); @@ -611,19 +615,26 @@ std::optional BlendFilterContents::RenderFilter( std::nullopt, GetAbsorbOpacity(), GetAlpha()); } - if (blend_mode_ <= Entity::kLastPipelineBlendMode) { - return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_, + BlendMode blend_mode = blend_mode_; + if (blend_mode == BlendMode::kPlus && + !IsAlphaClampedToOne( + renderer.GetContext()->GetCapabilities()->GetDefaultColorFormat())) { + blend_mode = BlendMode::kPlusAdvanced; + } + + if (blend_mode <= Entity::kLastPipelineBlendMode) { + return PipelineBlend(inputs, renderer, entity, coverage, blend_mode, foreground_color_, GetAbsorbOpacity(), GetAlpha()); } - if (blend_mode_ <= Entity::kLastAdvancedBlendMode) { + if (blend_mode <= Entity::kLastAdvancedBlendMode) { if (inputs.size() == 1 && foreground_color_.has_value() && GetAbsorbOpacity() == ColorFilterContents::AbsorbOpacity::kYes) { return CreateForegroundAdvancedBlend( inputs[0], renderer, entity, coverage, foreground_color_.value(), - blend_mode_, GetAlpha(), GetAbsorbOpacity()); + blend_mode, GetAlpha(), GetAbsorbOpacity()); } - return advanced_blend_proc_(inputs, renderer, entity, coverage, blend_mode_, + return advanced_blend_proc_(inputs, renderer, entity, coverage, blend_mode, foreground_color_, GetAbsorbOpacity(), GetAlpha()); } diff --git a/impeller/entity/contents/framebuffer_blend_contents.cc b/impeller/entity/contents/framebuffer_blend_contents.cc index c4a75ddd03ab4..cee9b5a904e4c 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.cc +++ b/impeller/entity/contents/framebuffer_blend_contents.cc @@ -118,6 +118,10 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, case BlendMode::kColor: pass.SetPipeline(renderer.GetFramebufferBlendColorPipeline(options)); break; + case BlendMode::kPlusAdvanced: + pass.SetPipeline( + renderer.GetFramebufferBlendPlusAdvancedPipeline(options)); + break; case BlendMode::kLuminosity: pass.SetPipeline(renderer.GetFramebufferBlendLuminosityPipeline(options)); break; diff --git a/impeller/entity/contents/framebuffer_blend_contents.h b/impeller/entity/contents/framebuffer_blend_contents.h index 5335055bd3f61..c8deee6450b25 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.h +++ b/impeller/entity/contents/framebuffer_blend_contents.h @@ -27,6 +27,7 @@ enum class BlendSelectValues { kHue, kSaturation, kColor, + kPlusAdvanced, kLuminosity, }; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index c128dd06e9747..a3664ed816cb9 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -941,6 +941,13 @@ bool EntityPass::OnRender( /// Setup advanced blends. /// + if (result.entity.GetBlendMode() == BlendMode::kPlus && + !IsAlphaClampedToOne(pass_context.GetPassTarget() + .GetRenderTarget() + .GetRenderTargetPixelFormat())) { + result.entity.SetBlendMode(BlendMode::kPlusAdvanced); + } + if (result.entity.GetBlendMode() > Entity::kLastPipelineBlendMode) { if (renderer.GetDeviceCapabilities().SupportsFramebufferFetch()) { auto src_contents = result.entity.GetContents(); diff --git a/impeller/entity/shaders/blending/advanced_blend.frag b/impeller/entity/shaders/blending/advanced_blend.frag index db444f522a092..07f72dab63af7 100644 --- a/impeller/entity/shaders/blending/advanced_blend.frag +++ b/impeller/entity/shaders/blending/advanced_blend.frag @@ -36,22 +36,33 @@ f16vec4 Sample(f16sampler2D texture_sampler, vec2 texture_coords) { } void main() { - f16vec4 dst = - IPHalfUnpremultiply(Sample(texture_sampler_dst, // sampler - v_dst_texture_coords // texture coordinates - )); - dst *= blend_info.dst_input_alpha; - f16vec4 src = blend_info.color_factor > 0.0hf - ? blend_info.color - : IPHalfUnpremultiply(Sample( - texture_sampler_src, // sampler - v_src_texture_coords // texture coordinates - )); - if (blend_info.color_factor == 0.0hf) { - src.a *= blend_info.src_input_alpha; - } + f16vec4 premultiplied_dst = + Sample(texture_sampler_dst, // sampler + v_dst_texture_coords // texture coordinates + ); + int nblend_type = int(blend_type); + + if (nblend_type == /*BlendSelectValues::kPlusAdvanced*/ 14) { + f16vec4 premultiplied_src = + Sample(texture_sampler_src, // sampler + v_src_texture_coords // texture coordinates + ); + frag_color = IPHalfPlusBlend(premultiplied_src, premultiplied_dst); + } else { + f16vec4 dst = IPHalfUnpremultiply(premultiplied_dst); + dst *= blend_info.dst_input_alpha; - f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, int(blend_type)); + f16vec4 src = blend_info.color_factor > 0.0hf + ? blend_info.color + : IPHalfUnpremultiply(Sample( + texture_sampler_src, // sampler + v_src_texture_coords // texture coordinates + )); + if (blend_info.color_factor == 0.0hf) { + src.a *= blend_info.src_input_alpha; + } - frag_color = IPApplyBlendedColor(dst, src, blend_result); + f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, nblend_type); + frag_color = IPApplyBlendedColor(dst, src, blend_result); + } } diff --git a/impeller/entity/shaders/blending/blend_select.glsl b/impeller/entity/shaders/blending/blend_select.glsl index 17c45c16fdcf4..b03e6eb520abd 100644 --- a/impeller/entity/shaders/blending/blend_select.glsl +++ b/impeller/entity/shaders/blending/blend_select.glsl @@ -20,6 +20,7 @@ // kHue, // kSaturation, // kColor, +// kPlusAdvanced, // 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) { @@ -65,7 +66,9 @@ f16vec3 AdvancedBlend(f16vec3 dst, f16vec3 src, int blend_type) { if (blend_type == 13) { return IPBlendColor(dst, src); } - if (blend_type == 14) { + // 14 is `PlusAdvanced`, it's handled in advanced_blend.frag and + // framebuffer_blend.frag. + if (blend_type == 15) { return IPBlendLuminosity(dst, src); } return f16vec3(0.0hf); diff --git a/impeller/entity/shaders/blending/framebuffer_blend.frag b/impeller/entity/shaders/blending/framebuffer_blend.frag index 6d03856b4a824..1eba2de9a9b3a 100644 --- a/impeller/entity/shaders/blending/framebuffer_blend.frag +++ b/impeller/entity/shaders/blending/framebuffer_blend.frag @@ -43,14 +43,21 @@ vec4 Sample(sampler2D texture_sampler, vec2 texture_coords) { } void main() { - f16vec4 dst = IPHalfUnpremultiply(f16vec4(ReadDestination())); - f16vec4 src = IPHalfUnpremultiply( + f16vec4 premultiplied_dst = f16vec4(ReadDestination()); + f16vec4 premultiplied_src = f16vec4(Sample(texture_sampler_src, // sampler v_src_texture_coords // texture coordinates - ))); - src.a *= frag_info.src_input_alpha; - - f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, int(blend_type)); - - frag_color = IPApplyBlendedColor(dst, src, blend_result); + )); + int nblend_type = int(blend_type); + + if (nblend_type == /*BlendSelectValues::kPlusAdvanced*/ 14) { + frag_color = IPHalfPlusBlend(premultiplied_src, premultiplied_dst); + } else { + f16vec4 dst = IPHalfUnpremultiply(premultiplied_dst); + f16vec4 src = IPHalfUnpremultiply(premultiplied_src); + src.a *= frag_info.src_input_alpha; + + f16vec3 blend_result = AdvancedBlend(dst.rgb, src.rgb, nblend_type); + frag_color = IPApplyBlendedColor(dst, src, blend_result); + } } diff --git a/impeller/geometry/color.cc b/impeller/geometry/color.cc index d2565e6e6fd1d..a8c70e1862359 100644 --- a/impeller/geometry/color.cc +++ b/impeller/geometry/color.cc @@ -276,6 +276,8 @@ Color Color::Blend(Color src, BlendMode blend_mode) const { return (src.Premultiply() * (1 - dst.alpha) + dst.Premultiply() * (1 - src.alpha)) .Unpremultiply(); + case BlendMode::kPlusAdvanced: + [[fallthrough]]; case BlendMode::kPlus: // r = min(s + d, 1) return (Min(src.Premultiply() + dst.Premultiply(), 1)).Unpremultiply(); diff --git a/impeller/geometry/color.h b/impeller/geometry/color.h index c90c696066ed6..59805e952ec02 100644 --- a/impeller/geometry/color.h +++ b/impeller/geometry/color.h @@ -45,6 +45,7 @@ V(Hue) \ V(Saturation) \ V(Color) \ + V(PlusAdvanced) \ V(Luminosity) namespace impeller { @@ -91,6 +92,7 @@ enum class BlendMode : uint8_t { kHue, kSaturation, kColor, + kPlusAdvanced, kLuminosity, kLast = kLuminosity, diff --git a/impeller/geometry/geometry_unittests.cc b/impeller/geometry/geometry_unittests.cc index aa1e5910b77eb..af9a2a1cfe9df 100644 --- a/impeller/geometry/geometry_unittests.cc +++ b/impeller/geometry/geometry_unittests.cc @@ -6,6 +6,7 @@ #include "impeller/geometry/geometry_asserts.h" #include +#include #include #include @@ -1450,107 +1451,112 @@ struct ColorBlendTestData { Color::LimeGreen().WithAlpha(0.75), Color::Black().WithAlpha(0.75)}; - // THIS RESULT TABLE IS GENERATED! - // - // Uncomment the `GenerateColorBlendResults` test below to print a new table - // after making changes to `Color::Blend`. - static constexpr Color kExpectedResults - [sizeof(kSourceColors)] - [static_cast>(BlendMode::kLast) + 1] = { - { - {0, 0, 0, 0}, // Clear - {1, 1, 1, 0.75}, // Source - {0.392157, 0.584314, 0.929412, 0.75}, // Destination - {0.878431, 0.916863, 0.985882, 0.9375}, // SourceOver - {0.513726, 0.667451, 0.943529, 0.9375}, // DestinationOver - {1, 1, 1, 0.5625}, // SourceIn - {0.392157, 0.584314, 0.929412, 0.5625}, // DestinationIn - {1, 1, 1, 0.1875}, // SourceOut - {0.392157, 0.584314, 0.929412, 0.1875}, // DestinationOut - {0.848039, 0.896078, 0.982353, 0.75}, // SourceATop - {0.544118, 0.688235, 0.947059, 0.75}, // DestinationATop - {0.696078, 0.792157, 0.964706, 0.375}, // Xor - {1, 1, 1, 1}, // Plus - {0.392157, 0.584314, 0.929412, 0.5625}, // Modulate - {0.878431, 0.916863, 0.985882, 0.9375}, // Screen - {0.74902, 0.916863, 0.985882, 0.9375}, // Overlay - {0.513726, 0.667451, 0.943529, 0.9375}, // Darken - {0.878431, 0.916863, 0.985882, 0.9375}, // Lighten - {0.878431, 0.916863, 0.985882, 0.9375}, // ColorDodge - {0.513725, 0.667451, 0.943529, 0.9375}, // ColorBurn - {0.878431, 0.916863, 0.985882, 0.9375}, // HardLight - {0.654166, 0.775505, 0.964318, 0.9375}, // SoftLight - {0.643137, 0.566275, 0.428235, 0.9375}, // Difference - {0.643137, 0.566275, 0.428235, 0.9375}, // Exclusion - {0.513726, 0.667451, 0.943529, 0.9375}, // Multiply - {0.617208, 0.655639, 0.724659, 0.9375}, // Hue - {0.617208, 0.655639, 0.724659, 0.9375}, // Saturation - {0.617208, 0.655639, 0.724659, 0.9375}, // Color - {0.878431, 0.916863, 0.985882, 0.9375}, // Luminosity - }, - { - {0, 0, 0, 0}, // Clear - {0.196078, 0.803922, 0.196078, 0.75}, // Source - {0.392157, 0.584314, 0.929412, 0.75}, // Destination - {0.235294, 0.76, 0.342745, 0.9375}, // SourceOver - {0.352941, 0.628235, 0.782745, 0.9375}, // DestinationOver - {0.196078, 0.803922, 0.196078, 0.5625}, // SourceIn - {0.392157, 0.584314, 0.929412, 0.5625}, // DestinationIn - {0.196078, 0.803922, 0.196078, 0.1875}, // SourceOut - {0.392157, 0.584314, 0.929412, 0.1875}, // DestinationOut - {0.245098, 0.74902, 0.379412, 0.75}, // SourceATop - {0.343137, 0.639216, 0.746078, 0.75}, // DestinationATop - {0.294118, 0.694118, 0.562745, 0.375}, // Xor - {0.441176, 1, 0.844118, 1}, // Plus - {0.0768935, 0.469742, 0.182238, 0.5625}, // Modulate - {0.424452, 0.828743, 0.79105, 0.9375}, // Screen - {0.209919, 0.779839, 0.757001, 0.9375}, // Overlay - {0.235294, 0.628235, 0.342745, 0.9375}, // Darken - {0.352941, 0.76, 0.782745, 0.9375}, // Lighten - {0.41033, 0.877647, 0.825098, 0.9375}, // ColorDodge - {0.117647, 0.567403, 0.609098, 0.9375}, // ColorBurn - {0.209919, 0.779839, 0.443783, 0.9375}, // HardLight - {0.266006, 0.693915, 0.758818, 0.9375}, // SoftLight - {0.235294, 0.409412, 0.665098, 0.9375}, // Difference - {0.378316, 0.546897, 0.681707, 0.9375}, // Exclusion - {0.163783, 0.559493, 0.334441, 0.9375}, // Multiply - {0.266235, 0.748588, 0.373686, 0.9375}, // Hue - {0.339345, 0.629787, 0.811502, 0.9375}, // Saturation - {0.241247, 0.765953, 0.348698, 0.9375}, // Color - {0.346988, 0.622282, 0.776792, 0.9375}, // Luminosity - }, - { - {0, 0, 0, 0}, // Clear - {0, 0, 0, 0.75}, // Source - {0.392157, 0.584314, 0.929412, 0.75}, // Destination - {0.0784314, 0.116863, 0.185882, 0.9375}, // SourceOver - {0.313726, 0.467451, 0.743529, 0.9375}, // DestinationOver - {0, 0, 0, 0.5625}, // SourceIn - {0.392157, 0.584314, 0.929412, 0.5625}, // DestinationIn - {0, 0, 0, 0.1875}, // SourceOut - {0.392157, 0.584314, 0.929412, 0.1875}, // DestinationOut - {0.0980392, 0.146078, 0.232353, 0.75}, // SourceATop - {0.294118, 0.438235, 0.697059, 0.75}, // DestinationATop - {0.196078, 0.292157, 0.464706, 0.375}, // Xor - {0.294118, 0.438235, 0.697059, 1}, // Plus - {0, 0, 0, 0.5625}, // Modulate - {0.313726, 0.467451, 0.743529, 0.9375}, // Screen - {0.0784314, 0.218039, 0.701176, 0.9375}, // Overlay - {0.0784314, 0.116863, 0.185882, 0.9375}, // Darken - {0.313726, 0.467451, 0.743529, 0.9375}, // Lighten - {0.313726, 0.467451, 0.743529, 0.9375}, // ColorDodge - {0.0784314, 0.116863, 0.185882, 0.9375}, // ColorBurn - {0.0784314, 0.116863, 0.185882, 0.9375}, // HardLight - {0.170704, 0.321716, 0.704166, 0.9375}, // SoftLight - {0.313726, 0.467451, 0.743529, 0.9375}, // Difference - {0.313726, 0.467451, 0.743529, 0.9375}, // Exclusion - {0.0784314, 0.116863, 0.185882, 0.9375}, // Multiply - {0.417208, 0.455639, 0.524659, 0.9375}, // Hue - {0.417208, 0.455639, 0.524659, 0.9375}, // Saturation - {0.417208, 0.455639, 0.524659, 0.9375}, // Color - {0.0784314, 0.116863, 0.185882, 0.9375}, // Luminosity - }, - }; + static const std::map + kExpectedResults[sizeof(kSourceColors)]; +}; + +// THIS RESULT TABLE IS GENERATED! +// +// Uncomment the `GenerateColorBlendResults` test below to print a new table +// after making changes to `Color::Blend`. +const std::map ColorBlendTestData::kExpectedResults[sizeof( + ColorBlendTestData::kSourceColors)] = { + { + {BlendMode::kClear, {0, 0, 0, 0}}, + {BlendMode::kSource, {1, 1, 1, 0.75}}, + {BlendMode::kDestination, {0.392157, 0.584314, 0.929412, 0.75}}, + {BlendMode::kSourceOver, {0.878431, 0.916863, 0.985882, 0.9375}}, + {BlendMode::kDestinationOver, {0.513726, 0.667451, 0.943529, 0.9375}}, + {BlendMode::kSourceIn, {1, 1, 1, 0.5625}}, + {BlendMode::kDestinationIn, {0.392157, 0.584314, 0.929412, 0.5625}}, + {BlendMode::kSourceOut, {1, 1, 1, 0.1875}}, + {BlendMode::kDestinationOut, {0.392157, 0.584314, 0.929412, 0.1875}}, + {BlendMode::kSourceATop, {0.848039, 0.896078, 0.982353, 0.75}}, + {BlendMode::kDestinationATop, {0.544118, 0.688235, 0.947059, 0.75}}, + {BlendMode::kXor, {0.696078, 0.792157, 0.964706, 0.375}}, + {BlendMode::kPlus, {1, 1, 1, 1}}, + {BlendMode::kModulate, {0.392157, 0.584314, 0.929412, 0.5625}}, + {BlendMode::kScreen, {0.878431, 0.916863, 0.985882, 0.9375}}, + {BlendMode::kOverlay, {0.74902, 0.916863, 0.985882, 0.9375}}, + {BlendMode::kDarken, {0.513726, 0.667451, 0.943529, 0.9375}}, + {BlendMode::kLighten, {0.878431, 0.916863, 0.985882, 0.9375}}, + {BlendMode::kColorDodge, {0.878431, 0.916863, 0.985882, 0.9375}}, + {BlendMode::kColorBurn, {0.513725, 0.667451, 0.943529, 0.9375}}, + {BlendMode::kHardLight, {0.878431, 0.916863, 0.985882, 0.9375}}, + {BlendMode::kSoftLight, {0.654166, 0.775505, 0.964318, 0.9375}}, + {BlendMode::kDifference, {0.643137, 0.566275, 0.428235, 0.9375}}, + {BlendMode::kExclusion, {0.643137, 0.566275, 0.428235, 0.9375}}, + {BlendMode::kMultiply, {0.513726, 0.667451, 0.943529, 0.9375}}, + {BlendMode::kHue, {0.617208, 0.655639, 0.724659, 0.9375}}, + {BlendMode::kSaturation, {0.617208, 0.655639, 0.724659, 0.9375}}, + {BlendMode::kColor, {0.617208, 0.655639, 0.724659, 0.9375}}, + {BlendMode::kPlusAdvanced, {1, 1, 1, 1}}, + {BlendMode::kLuminosity, {0.878431, 0.916863, 0.985882, 0.9375}}, + }, + { + {BlendMode::kClear, {0, 0, 0, 0}}, + {BlendMode::kSource, {0.196078, 0.803922, 0.196078, 0.75}}, + {BlendMode::kDestination, {0.392157, 0.584314, 0.929412, 0.75}}, + {BlendMode::kSourceOver, {0.235294, 0.76, 0.342745, 0.9375}}, + {BlendMode::kDestinationOver, {0.352941, 0.628235, 0.782745, 0.9375}}, + {BlendMode::kSourceIn, {0.196078, 0.803922, 0.196078, 0.5625}}, + {BlendMode::kDestinationIn, {0.392157, 0.584314, 0.929412, 0.5625}}, + {BlendMode::kSourceOut, {0.196078, 0.803922, 0.196078, 0.1875}}, + {BlendMode::kDestinationOut, {0.392157, 0.584314, 0.929412, 0.1875}}, + {BlendMode::kSourceATop, {0.245098, 0.74902, 0.379412, 0.75}}, + {BlendMode::kDestinationATop, {0.343137, 0.639216, 0.746078, 0.75}}, + {BlendMode::kXor, {0.294118, 0.694118, 0.562745, 0.375}}, + {BlendMode::kPlus, {0.441176, 1, 0.844118, 1}}, + {BlendMode::kModulate, {0.0768935, 0.469742, 0.182238, 0.5625}}, + {BlendMode::kScreen, {0.424452, 0.828743, 0.79105, 0.9375}}, + {BlendMode::kOverlay, {0.209919, 0.779839, 0.757001, 0.9375}}, + {BlendMode::kDarken, {0.235294, 0.628235, 0.342745, 0.9375}}, + {BlendMode::kLighten, {0.352941, 0.76, 0.782745, 0.9375}}, + {BlendMode::kColorDodge, {0.41033, 0.877647, 0.825098, 0.9375}}, + {BlendMode::kColorBurn, {0.117647, 0.567403, 0.609098, 0.9375}}, + {BlendMode::kHardLight, {0.209919, 0.779839, 0.443783, 0.9375}}, + {BlendMode::kSoftLight, {0.266006, 0.693915, 0.758818, 0.9375}}, + {BlendMode::kDifference, {0.235294, 0.409412, 0.665098, 0.9375}}, + {BlendMode::kExclusion, {0.378316, 0.546897, 0.681707, 0.9375}}, + {BlendMode::kMultiply, {0.163783, 0.559493, 0.334441, 0.9375}}, + {BlendMode::kHue, {0.266235, 0.748588, 0.373686, 0.9375}}, + {BlendMode::kSaturation, {0.339345, 0.629787, 0.811502, 0.9375}}, + {BlendMode::kColor, {0.241247, 0.765953, 0.348698, 0.9375}}, + {BlendMode::kPlusAdvanced, {0.441176, 1, 0.844118, 1}}, + {BlendMode::kLuminosity, {0.346988, 0.622282, 0.776792, 0.9375}}, + }, + { + {BlendMode::kClear, {0, 0, 0, 0}}, + {BlendMode::kSource, {0, 0, 0, 0.75}}, + {BlendMode::kDestination, {0.392157, 0.584314, 0.929412, 0.75}}, + {BlendMode::kSourceOver, {0.0784314, 0.116863, 0.185882, 0.9375}}, + {BlendMode::kDestinationOver, {0.313726, 0.467451, 0.743529, 0.9375}}, + {BlendMode::kSourceIn, {0, 0, 0, 0.5625}}, + {BlendMode::kDestinationIn, {0.392157, 0.584314, 0.929412, 0.5625}}, + {BlendMode::kSourceOut, {0, 0, 0, 0.1875}}, + {BlendMode::kDestinationOut, {0.392157, 0.584314, 0.929412, 0.1875}}, + {BlendMode::kSourceATop, {0.0980392, 0.146078, 0.232353, 0.75}}, + {BlendMode::kDestinationATop, {0.294118, 0.438235, 0.697059, 0.75}}, + {BlendMode::kXor, {0.196078, 0.292157, 0.464706, 0.375}}, + {BlendMode::kPlus, {0.294118, 0.438235, 0.697059, 1}}, + {BlendMode::kModulate, {0, 0, 0, 0.5625}}, + {BlendMode::kScreen, {0.313726, 0.467451, 0.743529, 0.9375}}, + {BlendMode::kOverlay, {0.0784314, 0.218039, 0.701176, 0.9375}}, + {BlendMode::kDarken, {0.0784314, 0.116863, 0.185882, 0.9375}}, + {BlendMode::kLighten, {0.313726, 0.467451, 0.743529, 0.9375}}, + {BlendMode::kColorDodge, {0.313726, 0.467451, 0.743529, 0.9375}}, + {BlendMode::kColorBurn, {0.0784314, 0.116863, 0.185882, 0.9375}}, + {BlendMode::kHardLight, {0.0784314, 0.116863, 0.185882, 0.9375}}, + {BlendMode::kSoftLight, {0.170704, 0.321716, 0.704166, 0.9375}}, + {BlendMode::kDifference, {0.313726, 0.467451, 0.743529, 0.9375}}, + {BlendMode::kExclusion, {0.313726, 0.467451, 0.743529, 0.9375}}, + {BlendMode::kMultiply, {0.0784314, 0.116863, 0.185882, 0.9375}}, + {BlendMode::kHue, {0.417208, 0.455639, 0.524659, 0.9375}}, + {BlendMode::kSaturation, {0.417208, 0.455639, 0.524659, 0.9375}}, + {BlendMode::kColor, {0.417208, 0.455639, 0.524659, 0.9375}}, + {BlendMode::kPlusAdvanced, {0.294118, 0.438235, 0.697059, 1}}, + {BlendMode::kLuminosity, {0.0784314, 0.116863, 0.185882, 0.9375}}, + }, }; /// To print a new ColorBlendTestData::kExpectedResults table, uncomment this @@ -1567,8 +1573,10 @@ TEST(GeometryTest, GenerateColorBlendResults) { blend_i < static_cast(BlendMode::kLast) + 1; blend_i++) { auto blend = static_cast(blend_i); Color c = ColorBlendTestData::kDestinationColor.Blend(source, blend); + o << "{ BlendMode::k" << BlendModeToString(blend) << ", "; o << "{" << c.red << "," << c.green << "," << c.blue << "," << c.alpha - << "}, // " << BlendModeToString(blend) << std::endl; + << "}"; + o << "}," << std::endl; } o << "},"; } @@ -1576,20 +1584,19 @@ TEST(GeometryTest, GenerateColorBlendResults) { } */ -#define _BLEND_MODE_RESULT_CHECK(blend_mode) \ - blend_i = static_cast(BlendMode::k##blend_mode); \ - expected = ColorBlendTestData::kExpectedResults[source_i][blend_i]; \ +#define _BLEND_MODE_RESULT_CHECK(blend_mode) \ + expected = ColorBlendTestData::kExpectedResults[source_i] \ + .find(BlendMode::k##blend_mode) \ + ->second; \ EXPECT_COLOR_NEAR(dst.Blend(src, BlendMode::k##blend_mode), expected); TEST(GeometryTest, ColorBlendReturnsExpectedResults) { - using BlendT = std::underlying_type_t; Color dst = ColorBlendTestData::kDestinationColor; for (size_t source_i = 0; source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color); source_i++) { Color src = ColorBlendTestData::kSourceColors[source_i]; - size_t blend_i; Color expected; IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_RESULT_CHECK) } diff --git a/impeller/golden_tests/golden_playground_test_mac.cc b/impeller/golden_tests/golden_playground_test_mac.cc index 75fea0f34072a..833a62bfbf0a1 100644 --- a/impeller/golden_tests/golden_playground_test_mac.cc +++ b/impeller/golden_tests/golden_playground_test_mac.cc @@ -138,9 +138,12 @@ void GoldenPlaygroundTest::SetUp() { std::filesystem::path icd_path = target_path / "vk_swiftshader_icd.json"; setenv("VK_ICD_FILENAMES", icd_path.c_str(), 1); + std::string test_name = GetTestName(); + bool enable_wide_gamut = test_name.find("WideGamut_") != std::string::npos; switch (GetParam()) { case PlaygroundBackend::kMetal: - pimpl_->screenshotter = std::make_unique(); + pimpl_->screenshotter = + std::make_unique(enable_wide_gamut); break; case PlaygroundBackend::kVulkan: { const std::unique_ptr& playground = @@ -160,16 +163,7 @@ void GoldenPlaygroundTest::SetUp() { break; } } - if (GetParam() == PlaygroundBackend::kMetal) { - pimpl_->screenshotter = std::make_unique(); - } else if (GetParam() == PlaygroundBackend::kVulkan) { - const std::unique_ptr& playground = - GetSharedVulkanPlayground(/*enable_validations=*/true); - pimpl_->screenshotter = - std::make_unique(playground); - } - std::string test_name = GetTestName(); if (std::find(kSkipTests.begin(), kSkipTests.end(), test_name) != kSkipTests.end()) { GTEST_SKIP_( diff --git a/impeller/golden_tests/golden_tests.cc b/impeller/golden_tests/golden_tests.cc index c519f367a1ddb..40a79cd173703 100644 --- a/impeller/golden_tests/golden_tests.cc +++ b/impeller/golden_tests/golden_tests.cc @@ -50,7 +50,8 @@ bool SaveScreenshot(std::unique_ptr screenshot) { class GoldenTests : public ::testing::Test { public: - GoldenTests() : screenshotter_(new MetalScreenshotter()) {} + GoldenTests() + : screenshotter_(new MetalScreenshotter(/*enable_wide_gamut=*/false)) {} MetalScreenshotter& Screenshotter() { return *screenshotter_; } diff --git a/impeller/golden_tests/metal_screenshotter.h b/impeller/golden_tests/metal_screenshotter.h index 582462a73f425..8104396bd8be5 100644 --- a/impeller/golden_tests/metal_screenshotter.h +++ b/impeller/golden_tests/metal_screenshotter.h @@ -18,7 +18,7 @@ namespace testing { /// playground backend. class MetalScreenshotter : public Screenshotter { public: - MetalScreenshotter(); + explicit MetalScreenshotter(bool enable_wide_gamut); std::unique_ptr MakeScreenshot( AiksContext& aiks_context, diff --git a/impeller/golden_tests/metal_screenshotter.mm b/impeller/golden_tests/metal_screenshotter.mm index 534884078a17f..f09cb10e03849 100644 --- a/impeller/golden_tests/metal_screenshotter.mm +++ b/impeller/golden_tests/metal_screenshotter.mm @@ -13,10 +13,11 @@ namespace impeller { namespace testing { -MetalScreenshotter::MetalScreenshotter() { +MetalScreenshotter::MetalScreenshotter(bool enable_wide_gamut) { FML_CHECK(::glfwInit() == GLFW_TRUE); - playground_ = - PlaygroundImpl::Create(PlaygroundBackend::kMetal, PlaygroundSwitches{}); + PlaygroundSwitches switches; + switches.enable_wide_gamut = enable_wide_gamut; + playground_ = PlaygroundImpl::Create(PlaygroundBackend::kMetal, switches); } std::unique_ptr MetalScreenshotter::MakeScreenshot( @@ -33,10 +34,6 @@ id metal_texture = std::static_pointer_cast(texture)->GetMTLTexture(); - if (metal_texture.pixelFormat != MTLPixelFormatBGRA8Unorm) { - return {}; - } - CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); CIImage* ciImage = [[CIImage alloc] initWithMTLTexture:metal_texture diff --git a/impeller/playground/backend/metal/playground_impl_mtl.mm b/impeller/playground/backend/metal/playground_impl_mtl.mm index 421d6eba3c46b..00babefd4c047 100644 --- a/impeller/playground/backend/metal/playground_impl_mtl.mm +++ b/impeller/playground/backend/metal/playground_impl_mtl.mm @@ -73,9 +73,12 @@ if (!window) { return; } - auto context = - ContextMTL::Create(ShaderLibraryMappingsForPlayground(), - is_gpu_disabled_sync_switch_, "Playground Library"); + auto context = ContextMTL::Create( + ShaderLibraryMappingsForPlayground(), is_gpu_disabled_sync_switch_, + "Playground Library", + switches.enable_wide_gamut + ? std::optional(PixelFormat::kR16G16B16A16Float) + : std::nullopt); if (!context) { return; } diff --git a/impeller/playground/compute_playground_test.cc b/impeller/playground/compute_playground_test.cc index 3df0e62a7260e..1abea913ebea4 100644 --- a/impeller/playground/compute_playground_test.cc +++ b/impeller/playground/compute_playground_test.cc @@ -25,7 +25,7 @@ void ComputePlaygroundTest::SetUp() { return; } - SetupContext(GetParam()); + SetupContext(GetParam(), switches_); SetupWindow(); start_time_ = fml::TimePoint::Now().ToEpochDelta(); diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index 4ed9e5af7efcb..ae4d7cd4dd3fb 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -120,10 +120,11 @@ bool Playground::SupportsBackend(PlaygroundBackend backend) { FML_UNREACHABLE(); } -void Playground::SetupContext(PlaygroundBackend backend) { +void Playground::SetupContext(PlaygroundBackend backend, + const PlaygroundSwitches& switches) { FML_CHECK(SupportsBackend(backend)); - impl_ = PlaygroundImpl::Create(backend, switches_); + impl_ = PlaygroundImpl::Create(backend, switches); if (!impl_) { FML_LOG(WARNING) << "PlaygroundImpl::Create failed."; return; diff --git a/impeller/playground/playground.h b/impeller/playground/playground.h index 9c6cde6467d6a..b15461272f3d5 100644 --- a/impeller/playground/playground.h +++ b/impeller/playground/playground.h @@ -57,7 +57,8 @@ class Playground { static bool ShouldOpenNewPlaygrounds(); - void SetupContext(PlaygroundBackend backend); + void SetupContext(PlaygroundBackend backend, + const PlaygroundSwitches& switches); void SetupWindow(); diff --git a/impeller/playground/playground_test.cc b/impeller/playground/playground_test.cc index 676c3b0412992..00ee371ce2fbb 100644 --- a/impeller/playground/playground_test.cc +++ b/impeller/playground/playground_test.cc @@ -28,7 +28,13 @@ void PlaygroundTest::SetUp() { ImpellerValidationErrorsSetFatal(true); - SetupContext(GetParam()); + // Test names that end with "WideGamut" will render with wide gamut support. + std::string test_name = flutter::testing::GetCurrentTestName(); + PlaygroundSwitches switches = switches_; + switches.enable_wide_gamut = + test_name.find("WideGamut/") != std::string::npos; + + SetupContext(GetParam(), switches); SetupWindow(); } diff --git a/impeller/playground/switches.h b/impeller/playground/switches.h index be49fb0191a9b..6b9df55eb7642 100644 --- a/impeller/playground/switches.h +++ b/impeller/playground/switches.h @@ -33,6 +33,8 @@ struct PlaygroundSwitches { /// bool use_angle = false; + bool enable_wide_gamut = false; + PlaygroundSwitches(); explicit PlaygroundSwitches(const fml::CommandLine& args); diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index 6497871b28b25..dd11641665128 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -43,7 +43,8 @@ class ContextMTL final : public Context, static std::shared_ptr Create( const std::vector>& shader_libraries_data, std::shared_ptr is_gpu_disabled_sync_switch, - const std::string& label); + const std::string& label, + std::optional pixel_format_override = std::nullopt); static std::shared_ptr Create( id device, @@ -133,11 +134,11 @@ class ContextMTL final : public Context, std::shared_ptr command_queue_ip_; bool is_valid_ = false; - ContextMTL( - id device, - id command_queue, - NSArray>* shader_libraries, - std::shared_ptr is_gpu_disabled_sync_switch); + ContextMTL(id device, + id command_queue, + NSArray>* shader_libraries, + std::shared_ptr is_gpu_disabled_sync_switch, + std::optional pixel_format_override = std::nullopt); std::shared_ptr CreateCommandBufferInQueue( id queue) const; diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 623f3c8335f4c..6248368687451 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -75,7 +75,8 @@ static bool DeviceSupportsComputeSubgroups(id device) { id device, id command_queue, NSArray>* shader_libraries, - std::shared_ptr is_gpu_disabled_sync_switch) + std::shared_ptr is_gpu_disabled_sync_switch, + std::optional pixel_format_override) : device_(device), command_queue_(command_queue), is_gpu_disabled_sync_switch_(std::move(is_gpu_disabled_sync_switch)) { @@ -128,7 +129,9 @@ static bool DeviceSupportsComputeSubgroups(id device) { } device_capabilities_ = - InferMetalCapabilities(device_, PixelFormat::kB8G8R8A8UNormInt); + InferMetalCapabilities(device_, pixel_format_override.has_value() + ? pixel_format_override.value() + : PixelFormat::kB8G8R8A8UNormInt); command_queue_ip_ = std::make_shared(); #ifdef IMPELLER_DEBUG gpu_tracer_ = std::make_shared(); @@ -238,17 +241,18 @@ static bool DeviceSupportsComputeSubgroups(id device) { std::shared_ptr ContextMTL::Create( const std::vector>& shader_libraries_data, std::shared_ptr is_gpu_disabled_sync_switch, - const std::string& library_label) { + const std::string& library_label, + std::optional pixel_format_override) { auto device = CreateMetalDevice(); auto command_queue = CreateMetalCommandQueue(device); if (!command_queue) { return nullptr; } - auto context = std::shared_ptr( - new ContextMTL(device, command_queue, - MTLShaderLibraryFromFileData(device, shader_libraries_data, - library_label), - std::move(is_gpu_disabled_sync_switch))); + auto context = std::shared_ptr(new ContextMTL( + device, command_queue, + MTLShaderLibraryFromFileData(device, shader_libraries_data, + library_label), + std::move(is_gpu_disabled_sync_switch), pixel_format_override)); if (!context->IsValid()) { FML_LOG(ERROR) << "Could not create Metal context."; return nullptr; diff --git a/impeller/runtime_stage/runtime_stage_unittests.cc b/impeller/runtime_stage/runtime_stage_unittests.cc index 8315c6af7c455..2dc646d3a640b 100644 --- a/impeller/runtime_stage/runtime_stage_unittests.cc +++ b/impeller/runtime_stage/runtime_stage_unittests.cc @@ -62,6 +62,7 @@ TEST_P(RuntimeStageTest, CanReadUniforms) { ASSERT_TRUE(stage->IsValid()); switch (GetBackend()) { case PlaygroundBackend::kMetal: + [[fallthrough]]; case PlaygroundBackend::kOpenGLES: { ASSERT_EQ(stage->GetUniforms().size(), 17u); { diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index aae87f0f42e8c..9c13bcb384302 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -57,6 +57,11 @@ impeller_Play_AiksTest_BlendModeMultiply_Vulkan.png impeller_Play_AiksTest_BlendModeOverlay_Metal.png impeller_Play_AiksTest_BlendModeOverlay_OpenGLES.png impeller_Play_AiksTest_BlendModeOverlay_Vulkan.png +impeller_Play_AiksTest_BlendModePlusAdvanced_Metal.png +impeller_Play_AiksTest_BlendModePlusAdvanced_OpenGLES.png +impeller_Play_AiksTest_BlendModePlusAdvanced_Vulkan.png +impeller_Play_AiksTest_BlendModePlusAlphaColorFilterWideGamut_Metal.png +impeller_Play_AiksTest_BlendModePlusAlphaWideGamut_Metal.png impeller_Play_AiksTest_BlendModePlus_Metal.png impeller_Play_AiksTest_BlendModePlus_OpenGLES.png impeller_Play_AiksTest_BlendModePlus_Vulkan.png