From 5f0b94f50d5c31c3a58aafe02f2d4dd614211dcb Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 18 Mar 2025 19:03:30 +0000 Subject: [PATCH] [Impeller] Return an empty contents in Paint::CreateContents if a runtime effect sampler is invalid (#165165) Callers of Paint::CreateContents expect that the result is not null. See https://github.com/flutter/flutter/issues/165119 --- .../aiks_dl_runtime_effect_unittests.cc | 28 +++++++++++++++++++ .../flutter/impeller/display_list/paint.cc | 10 +++++-- .../testing/impeller_golden_tests_output.txt | 3 ++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_runtime_effect_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_runtime_effect_unittests.cc index 1bfcbd62ed..0012ce54d0 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_runtime_effect_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_runtime_effect_unittests.cc @@ -108,5 +108,33 @@ TEST_P(AiksTest, CanRenderRuntimeEffectFilter) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(AiksTest, RuntimeEffectWithInvalidSamplerDoesNotCrash) { + ScopedValidationDisable disable_validation; + + // Create a sampler that is not usable as an input to the runtime effect. + std::vector colors = {flutter::DlColor::kBlue(), + flutter::DlColor::kRed()}; + const float stops[2] = {0.0, 1.0}; + auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0}, + 2, colors.data(), stops, + flutter::DlTileMode::kClamp); + std::vector> sampler_inputs = { + linear, + }; + + auto uniform_data = std::make_shared>(); + uniform_data->resize(sizeof(Vector2)); + + DlPaint paint; + paint.setColorSource( + MakeRuntimeEffect(this, "runtime_stage_filter_example.frag.iplr", + uniform_data, sampler_inputs)); + + DisplayListBuilder builder; + builder.DrawPaint(paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + } // namespace testing } // namespace impeller diff --git a/engine/src/flutter/impeller/display_list/paint.cc b/engine/src/flutter/impeller/display_list/paint.cc index 97e3f68c6e..e5d03980ff 100644 --- a/engine/src/flutter/impeller/display_list/paint.cc +++ b/engine/src/flutter/impeller/display_list/paint.cc @@ -218,11 +218,17 @@ std::shared_ptr Paint::CreateContents() const { for (auto& sampler : samplers) { if (sampler == nullptr) { - return nullptr; + VALIDATION_LOG << "Runtime effect sampler is null"; + auto contents = std::make_shared(); + contents->SetColor(Color::BlackTransparent()); + return contents; } auto* image = sampler->asImage(); if (!sampler->asImage()) { - return nullptr; + VALIDATION_LOG << "Runtime effect sampler is not an image"; + auto contents = std::make_shared(); + contents->SetColor(Color::BlackTransparent()); + return contents; } FML_DCHECK(image->image()->impeller_texture()); texture_inputs.push_back({ diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index 4fd15e6f6f..32bcc2e45e 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -877,6 +877,9 @@ impeller_Play_AiksTest_ReleasesTextureOnTeardown_Vulkan.png impeller_Play_AiksTest_RotateColorFilteredPath_Metal.png impeller_Play_AiksTest_RotateColorFilteredPath_OpenGLES.png impeller_Play_AiksTest_RotateColorFilteredPath_Vulkan.png +impeller_Play_AiksTest_RuntimeEffectWithInvalidSamplerDoesNotCrash_Metal.png +impeller_Play_AiksTest_RuntimeEffectWithInvalidSamplerDoesNotCrash_OpenGLES.png +impeller_Play_AiksTest_RuntimeEffectWithInvalidSamplerDoesNotCrash_Vulkan.png impeller_Play_AiksTest_SaveLayerDrawsBehindSubsequentEntities_Metal.png impeller_Play_AiksTest_SaveLayerDrawsBehindSubsequentEntities_OpenGLES.png impeller_Play_AiksTest_SaveLayerDrawsBehindSubsequentEntities_Vulkan.png