Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fc36579

Browse files
committed
[Impeller] backfilled blur unit tests
2 parents b0d6ba1 + 9b1fb10 commit fc36579

File tree

3 files changed

+280
-0
lines changed

3 files changed

+280
-0
lines changed

impeller/entity/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ impeller_component("entity_unittests") {
240240
testonly = true
241241

242242
sources = [
243+
"contents/filters/directional_gaussian_blur_filter_contents_unittests.cc",
243244
"contents/filters/inputs/filter_input_unittests.cc",
244245
"entity_playground.cc",
245246
"entity_playground.h",
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/testing/testing.h"
6+
#include "gmock/gmock.h"
7+
#include "impeller/entity/contents/content_context.h"
8+
#include "impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h"
9+
#include "impeller/renderer/testing/mocks.h"
10+
11+
namespace impeller {
12+
namespace testing {
13+
14+
using ::testing::_;
15+
using ::testing::An;
16+
using ::testing::Invoke;
17+
using ::testing::Return;
18+
using ::testing::ReturnRef;
19+
20+
namespace {
21+
22+
Scalar CalculateSigmaForBlurRadius(Scalar blur_radius) {
23+
// See Sigma.h
24+
return (blur_radius / kKernelRadiusPerSigma) + 0.5;
25+
}
26+
} // namespace
27+
28+
class DirectionalGaussianBlurFilterContentsTest : public ::testing::Test {
29+
public:
30+
void SetUp() override { capabilities_ = mock_capabilities_; }
31+
32+
std::shared_ptr<MockCapabilities> mock_capabilities_ =
33+
std::make_shared<MockCapabilities>();
34+
std::shared_ptr<const Capabilities> capabilities_;
35+
};
36+
37+
TEST_F(DirectionalGaussianBlurFilterContentsTest, CoverageWithEffectTransform) {
38+
TextureDescriptor desc = {
39+
.size = ISize(100, 100),
40+
};
41+
Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
42+
auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
43+
contents->SetSigma(Sigma{sigma_radius_1});
44+
contents->SetDirection({1.0, 0.0});
45+
std::shared_ptr<MockTexture> texture = std::make_shared<MockTexture>(desc);
46+
EXPECT_CALL(*texture, GetSize()).WillRepeatedly(Return(ISize(100, 100)));
47+
FilterInput::Vector inputs = {FilterInput::Make(texture)};
48+
Entity entity;
49+
entity.SetTransformation(Matrix::MakeTranslation({100, 100, 0}));
50+
std::optional<Rect> coverage = contents->GetFilterCoverage(
51+
inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
52+
ASSERT_EQ(coverage, Rect::MakeLTRB(100 - 2, 100, 200 + 2, 200));
53+
}
54+
55+
TEST_F(DirectionalGaussianBlurFilterContentsTest, FilterSourceCoverage) {
56+
Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
57+
auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
58+
contents->SetSigma(Sigma{sigma_radius_1});
59+
contents->SetDirection({1.0, 0.0});
60+
std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
61+
/*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
62+
/*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
63+
ASSERT_EQ(coverage, Rect::MakeLTRB(100 - 2, 100, 200 + 2, 200));
64+
}
65+
66+
TEST_F(DirectionalGaussianBlurFilterContentsTest, RenderNoCoverage) {
67+
Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
68+
auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
69+
contents->SetSigma(Sigma{sigma_radius_1});
70+
contents->SetDirection({1.0, 0.0});
71+
auto mock_context = std::make_shared<MockImpellerContext>();
72+
auto mock_typographer_context = std::make_shared<MockTypographerContext>();
73+
auto mock_allocator = std::make_shared<MockAllocator>();
74+
auto mock_render_target_allocator =
75+
std::make_shared<MockRenderTargetAllocator>(mock_allocator);
76+
ContentContext renderer(mock_context, mock_typographer_context,
77+
mock_render_target_allocator);
78+
Entity entity;
79+
Rect coverage_hint = Rect::MakeLTRB(0, 0, 0, 0);
80+
std::optional<Entity> result =
81+
contents->GetEntity(renderer, entity, coverage_hint);
82+
ASSERT_FALSE(result.has_value());
83+
}
84+
85+
TEST_F(DirectionalGaussianBlurFilterContentsTest, RenderSomething) {
86+
TextureDescriptor desc = {
87+
.size = ISize(100, 100),
88+
};
89+
std::shared_ptr<MockTexture> texture = std::make_shared<MockTexture>(desc);
90+
EXPECT_CALL(*texture, GetSize()).WillRepeatedly(Return(ISize(100, 100)));
91+
Scalar sigma_radius_1 = CalculateSigmaForBlurRadius(1.0);
92+
auto contents = std::make_unique<DirectionalGaussianBlurFilterContents>();
93+
contents->SetSigma(Sigma{sigma_radius_1});
94+
contents->SetDirection({1.0, 0.0});
95+
contents->SetInputs({FilterInput::Make(texture)});
96+
auto mock_context = std::make_shared<MockImpellerContext>();
97+
EXPECT_CALL(*mock_context, GetCapabilities())
98+
.WillRepeatedly(ReturnRef(capabilities_));
99+
EXPECT_CALL(*mock_context, IsValid()).WillRepeatedly(Return(true));
100+
auto mock_sampler_library = std::make_shared<MockSamplerLibrary>();
101+
auto mock_shader_library = std::make_shared<MockShaderLibrary>();
102+
auto mock_pipeline_library = std::make_shared<MockPipelineLibrary>();
103+
EXPECT_CALL(*mock_pipeline_library, GetPipeline(An<PipelineDescriptor>()))
104+
.WillRepeatedly(
105+
Invoke([&mock_pipeline_library](PipelineDescriptor descriptor) {
106+
PipelineFuture<PipelineDescriptor> result;
107+
std::promise<std::shared_ptr<Pipeline<PipelineDescriptor>>> promise;
108+
auto mock_pipeline =
109+
std::make_shared<MockPipeline<PipelineDescriptor>>(
110+
mock_pipeline_library, descriptor);
111+
EXPECT_CALL(*mock_pipeline, IsValid()).WillRepeatedly(Return(true));
112+
promise.set_value(mock_pipeline);
113+
result.descriptor = descriptor;
114+
result.future = promise.get_future();
115+
return result;
116+
}));
117+
EXPECT_CALL(*mock_shader_library, GetFunction(_, _))
118+
.WillRepeatedly(Invoke([](std::string_view name, ShaderStage stage) {
119+
return std::make_shared<MockShaderFunction>(UniqueID(),
120+
std::string(name), stage);
121+
}));
122+
EXPECT_CALL(*mock_context, GetSamplerLibrary())
123+
.WillRepeatedly(Return(mock_sampler_library));
124+
EXPECT_CALL(*mock_context, GetShaderLibrary())
125+
.WillRepeatedly(Return(mock_shader_library));
126+
EXPECT_CALL(*mock_context, GetPipelineLibrary())
127+
.WillRepeatedly(Return(mock_pipeline_library));
128+
EXPECT_CALL(*mock_context, CreateCommandBuffer())
129+
.WillRepeatedly(Invoke(([&mock_context]() {
130+
auto result = std::make_shared<MockCommandBuffer>(mock_context);
131+
EXPECT_CALL(*result, IsValid()).WillRepeatedly(Return(true));
132+
EXPECT_CALL(*result, OnSubmitCommands(_)).WillRepeatedly(Return(true));
133+
EXPECT_CALL(*result, OnCreateRenderPass(_))
134+
.WillRepeatedly(
135+
Invoke(([&mock_context](const RenderTarget& render_target) {
136+
auto result = std::make_shared<MockRenderPass>(mock_context,
137+
render_target);
138+
EXPECT_CALL(*result, IsValid).WillRepeatedly(Return(true));
139+
EXPECT_CALL(*result, OnEncodeCommands(_))
140+
.WillRepeatedly(Return(true));
141+
return result;
142+
})));
143+
return result;
144+
})));
145+
auto mock_typographer_context = std::make_shared<MockTypographerContext>();
146+
auto mock_allocator = std::make_shared<MockAllocator>();
147+
auto mock_render_target_allocator =
148+
std::make_shared<MockRenderTargetAllocator>(mock_allocator);
149+
EXPECT_CALL(*mock_render_target_allocator, CreateTexture(_))
150+
.WillRepeatedly(Invoke(([](const TextureDescriptor& desc) {
151+
auto result = std::make_shared<MockTexture>(desc);
152+
EXPECT_CALL(*result, IsValid()).WillRepeatedly(Return(true));
153+
return result;
154+
})));
155+
ContentContext renderer(mock_context, mock_typographer_context,
156+
mock_render_target_allocator);
157+
Entity entity;
158+
Rect coverage_hint = Rect::MakeLTRB(0, 0, 0, 0);
159+
std::optional<Entity> result =
160+
contents->GetEntity(renderer, entity, coverage_hint);
161+
ASSERT_TRUE(result.has_value());
162+
ASSERT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
163+
}
164+
165+
} // namespace testing
166+
} // namespace impeller

impeller/renderer/testing/mocks.h

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
#include "impeller/core/texture.h"
1010
#include "impeller/renderer/command_buffer.h"
1111
#include "impeller/renderer/context.h"
12+
#include "impeller/renderer/pipeline_library.h"
13+
#include "impeller/renderer/render_pass.h"
1214
#include "impeller/renderer/render_target.h"
15+
#include "impeller/renderer/sampler_library.h"
16+
#include "impeller/renderer/shader_function.h"
17+
#include "impeller/typographer/typographer_context.h"
1318

1419
namespace impeller {
1520
namespace testing {
@@ -164,5 +169,113 @@ class MockTexture : public Texture {
164169
(override));
165170
};
166171

172+
class MockTypographerContext : public TypographerContext {
173+
public:
174+
MOCK_METHOD(std::shared_ptr<GlyphAtlas>,
175+
CreateGlyphAtlas,
176+
(Context & context,
177+
GlyphAtlas::Type type,
178+
std::shared_ptr<GlyphAtlasContext> atlas_context,
179+
const FontGlyphMap& font_glyph_map),
180+
(const, override));
181+
MOCK_METHOD(std::shared_ptr<GlyphAtlasContext>,
182+
CreateGlyphAtlasContext,
183+
(),
184+
(const, override));
185+
};
186+
187+
class MockRenderTargetAllocator : public RenderTargetAllocator {
188+
public:
189+
MockRenderTargetAllocator(std::shared_ptr<Allocator> allocator)
190+
: RenderTargetAllocator(allocator) {}
191+
MOCK_METHOD(std::shared_ptr<Texture>,
192+
CreateTexture,
193+
(const TextureDescriptor& desc),
194+
(override));
195+
};
196+
197+
class MockCapabilities : public Capabilities {
198+
public:
199+
MOCK_METHOD(bool, SupportsOffscreenMSAA, (), (const, override));
200+
MOCK_METHOD(bool, SupportsImplicitResolvingMSAA, (), (const, override));
201+
MOCK_METHOD(bool, SupportsSSBO, (), (const, override));
202+
MOCK_METHOD(bool, SupportsBufferToTextureBlits, (), (const, override));
203+
MOCK_METHOD(bool, SupportsTextureToTextureBlits, (), (const, override));
204+
MOCK_METHOD(bool, SupportsFramebufferFetch, (), (const, override));
205+
MOCK_METHOD(bool, SupportsCompute, (), (const, override));
206+
MOCK_METHOD(bool, SupportsComputeSubgroups, (), (const, override));
207+
MOCK_METHOD(bool, SupportsReadFromOnscreenTexture, (), (const, override));
208+
MOCK_METHOD(bool, SupportsReadFromResolve, (), (const, override));
209+
MOCK_METHOD(bool, SupportsDecalSamplerAddressMode, (), (const, override));
210+
MOCK_METHOD(bool, SupportsDeviceTransientTextures, (), (const, override));
211+
MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override));
212+
MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override));
213+
MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override));
214+
};
215+
216+
class MockRenderPass : public RenderPass {
217+
public:
218+
MockRenderPass(std::weak_ptr<const Context> context,
219+
const RenderTarget& target)
220+
: RenderPass(context, target) {}
221+
MOCK_METHOD(bool, IsValid, (), (const, override));
222+
MOCK_METHOD(void, OnSetLabel, (std::string), (override));
223+
MOCK_METHOD(bool, OnEncodeCommands, (const Context&), (const, override));
224+
};
225+
226+
class MockSamplerLibrary : public SamplerLibrary {
227+
public:
228+
MOCK_METHOD(std::shared_ptr<const Sampler>,
229+
GetSampler,
230+
(SamplerDescriptor),
231+
(override));
232+
};
233+
234+
class MockShaderLibrary : public ShaderLibrary {
235+
public:
236+
MOCK_METHOD(bool, IsValid, (), (const, override));
237+
MOCK_METHOD(std::shared_ptr<const ShaderFunction>,
238+
GetFunction,
239+
(std::string_view name, ShaderStage stage),
240+
(override));
241+
MOCK_METHOD(void,
242+
UnregisterFunction,
243+
(std::string name, ShaderStage stage),
244+
(override));
245+
};
246+
247+
class MockShaderFunction : public ShaderFunction {
248+
public:
249+
MockShaderFunction(UniqueID parent_library_id,
250+
std::string name,
251+
ShaderStage stage)
252+
: ShaderFunction(parent_library_id, name, stage) {}
253+
};
254+
255+
class MockPipelineLibrary : public PipelineLibrary {
256+
public:
257+
MOCK_METHOD(bool, IsValid, (), (const, override));
258+
MOCK_METHOD(PipelineFuture<PipelineDescriptor>,
259+
GetPipeline,
260+
(PipelineDescriptor descriptor),
261+
(override));
262+
MOCK_METHOD(PipelineFuture<ComputePipelineDescriptor>,
263+
GetPipeline,
264+
(ComputePipelineDescriptor descriptor),
265+
(override));
266+
MOCK_METHOD(void,
267+
RemovePipelinesWithEntryPoint,
268+
(std::shared_ptr<const ShaderFunction> function),
269+
(override));
270+
};
271+
272+
template <typename T>
273+
class MockPipeline : public Pipeline<T> {
274+
public:
275+
MockPipeline(std::weak_ptr<PipelineLibrary> library, T desc)
276+
: Pipeline<T>(library, desc) {}
277+
MOCK_METHOD(bool, IsValid, (), (const, override));
278+
};
279+
167280
} // namespace testing
168281
} // namespace impeller

0 commit comments

Comments
 (0)