7#include "gmock/gmock.h"
17#define IMPELLER_RAND arc4random
19#define IMPELLER_RAND rand
31 const std::function<
float(
float)>& func,
35 const double delta = 1e-6;
38 static const int kMaxIterations = 1000;
43 double derivative = (func(
x + delta) - func(
x)) / delta;
44 x =
x - fx / derivative;
45 if (++count > kMaxIterations) {
47 "Did not converge on answer.");
49 }
while (std::abs(fx) > tolerance ||
55Scalar GetCoefficient(
const Vector4& vec) {
59Vector2 GetUVOffset(
const Vector4& vec) {
65 const Matrix& effect_transform) {
78 return LowerBoundNewtonianMethod(f, radius, 2.f, 0.001f);
87 std::shared_ptr<CommandBuffer> command_buffer =
89 if (!command_buffer) {
94 "Clear Subpass",
size, command_buffer,
100 ->Submit({command_buffer})
105 if (render_target.ok()) {
106 return render_target.value().GetRenderTargetTexture();
129 std::optional<Rect> coverage =
131 ASSERT_FALSE(coverage.has_value());
142 std::optional<Rect> coverage =
150 CalculateSigmaForBlurRadius(1.0,
Matrix());
151 ASSERT_TRUE(sigma_radius_1.
ok());
153 sigma_radius_1.
value(),
160 std::optional<Rect> coverage =
163 EXPECT_TRUE(coverage.has_value());
164 if (coverage.has_value()) {
171 CalculateSigmaForBlurRadius(1.0,
Matrix());
172 ASSERT_TRUE(sigma_radius_1.
ok());
174 sigma_radius_1.
value(),
178 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
182 std::optional<Rect> coverage =
185 EXPECT_TRUE(coverage.has_value());
186 if (coverage.has_value()) {
194 CalculateSigmaForBlurRadius(1.0, effect_transform);
195 ASSERT_TRUE(sigma_radius_1.ok());
197 sigma_radius_1.value(),
201 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
205 std::optional<Rect> coverage =
207 EXPECT_TRUE(coverage.has_value());
208 if (coverage.has_value()) {
216 CalculateSigmaForBlurRadius(1.0,
Matrix());
217 ASSERT_TRUE(sigma_radius_1.
ok());
218 auto contents = std::make_unique<GaussianBlurFilterContents>(
222 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
225 EXPECT_TRUE(coverage.has_value());
226 if (coverage.has_value()) {
234 CalculateSigmaForBlurRadius(1.0,
Matrix());
235 ASSERT_TRUE(sigma_radius_1.
ok());
236 auto contents = std::make_unique<GaussianBlurFilterContents>(
242 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
245 ASSERT_TRUE(coverage.has_value());
246 if (coverage.has_value()) {
266 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
268 CalculateSigmaForBlurRadius(1.0,
Matrix());
269 ASSERT_TRUE(sigma_radius_1.
ok());
270 auto contents = std::make_unique<GaussianBlurFilterContents>(
275 std::shared_ptr<ContentContext> renderer = GetContentContext();
278 std::optional<Entity> result =
279 contents->GetEntity(*renderer, entity, {});
280 EXPECT_TRUE(result.has_value());
281 if (result.has_value()) {
283 std::optional<Rect> result_coverage = result.value().GetCoverage();
284 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
285 EXPECT_TRUE(result_coverage.has_value());
286 EXPECT_TRUE(contents_coverage.has_value());
287 if (result_coverage.has_value() && contents_coverage.has_value()) {
288 EXPECT_TRUE(
RectNear(contents_coverage.value(),
297 RenderCoverageMatchesGetCoverageTranslate) {
298 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
300 CalculateSigmaForBlurRadius(1.0,
Matrix());
301 ASSERT_TRUE(sigma_radius_1.
ok());
302 auto contents = std::make_unique<GaussianBlurFilterContents>(
307 std::shared_ptr<ContentContext> renderer = GetContentContext();
311 std::optional<Entity> result =
312 contents->GetEntity(*renderer, entity, {});
314 EXPECT_TRUE(result.has_value());
315 if (result.has_value()) {
317 std::optional<Rect> result_coverage = result.value().GetCoverage();
318 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
319 EXPECT_TRUE(result_coverage.has_value());
320 EXPECT_TRUE(contents_coverage.has_value());
321 if (result_coverage.has_value() && contents_coverage.has_value()) {
322 EXPECT_TRUE(
RectNear(contents_coverage.value(),
331 RenderCoverageMatchesGetCoverageRotated) {
332 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(400, 300));
334 CalculateSigmaForBlurRadius(1.0,
Matrix());
335 auto contents = std::make_unique<GaussianBlurFilterContents>(
340 std::shared_ptr<ContentContext> renderer = GetContentContext();
346 std::optional<Entity> result =
347 contents->GetEntity(*renderer, entity, {});
348 EXPECT_TRUE(result.has_value());
349 if (result.has_value()) {
351 std::optional<Rect> result_coverage = result.value().GetCoverage();
352 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
353 EXPECT_TRUE(result_coverage.has_value());
354 EXPECT_TRUE(contents_coverage.has_value());
355 if (result_coverage.has_value() && contents_coverage.has_value()) {
356 EXPECT_TRUE(
RectNear(contents_coverage.value(),
365 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
371 EXPECT_TRUE(uvs_bounds.has_value());
372 if (uvs_bounds.has_value()) {
378 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
379 auto texture_contents = std::make_shared<TextureContents>();
381 texture_contents->SetTexture(
texture);
386 CalculateSigmaForBlurRadius(1.0,
Matrix());
387 auto contents = std::make_unique<GaussianBlurFilterContents>(
392 std::shared_ptr<ContentContext> renderer = GetContentContext();
395 std::optional<Entity> result =
396 contents->GetEntity(*renderer, entity, {});
397 EXPECT_TRUE(result.has_value());
398 if (result.has_value()) {
400 std::optional<Rect> result_coverage = result.value().GetCoverage();
401 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
402 EXPECT_TRUE(result_coverage.has_value());
403 EXPECT_TRUE(contents_coverage.has_value());
404 if (result_coverage.has_value() && contents_coverage.has_value()) {
405 EXPECT_TRUE(
RectNear(result_coverage.value(), contents_coverage.value()));
406 EXPECT_TRUE(
RectNear(result_coverage.value(),
413 TextureContentsWithDestinationRectScaled) {
414 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
415 auto texture_contents = std::make_shared<TextureContents>();
417 texture_contents->SetTexture(
texture);
422 CalculateSigmaForBlurRadius(1.0,
Matrix());
423 auto contents = std::make_unique<GaussianBlurFilterContents>(
428 std::shared_ptr<ContentContext> renderer = GetContentContext();
432 std::optional<Entity> result =
433 contents->GetEntity(*renderer, entity, {});
434 EXPECT_TRUE(result.has_value());
435 if (result.has_value()) {
437 std::optional<Rect> result_coverage = result.value().GetCoverage();
438 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
439 EXPECT_TRUE(result_coverage.has_value());
440 EXPECT_TRUE(contents_coverage.has_value());
441 if (result_coverage.has_value() && contents_coverage.has_value()) {
442 EXPECT_TRUE(
RectNear(result_coverage.value(), contents_coverage.value()));
446 EXPECT_TRUE(
RectNear(contents_coverage.value(),
454 std::shared_ptr<Texture>
texture = MakeTexture(
ISize(100, 100));
455 auto texture_contents = std::make_shared<TextureContents>();
457 texture_contents->SetTexture(
texture);
462 CalculateSigmaForBlurRadius(1.0, effect_transform);
463 ASSERT_TRUE(sigma_radius_1.
ok());
464 auto contents = std::make_unique<GaussianBlurFilterContents>(
469 contents->SetEffectTransform(effect_transform);
470 std::shared_ptr<ContentContext> renderer = GetContentContext();
473 std::optional<Entity> result =
474 contents->GetEntity(*renderer, entity, {});
475 EXPECT_TRUE(result.has_value());
476 if (result.has_value()) {
478 std::optional<Rect> result_coverage = result.value().GetCoverage();
479 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
480 EXPECT_TRUE(result_coverage.has_value());
481 EXPECT_TRUE(contents_coverage.has_value());
482 if (result_coverage.has_value() && contents_coverage.has_value()) {
483 EXPECT_TRUE(
RectNear(result_coverage.value(), contents_coverage.value()));
484 EXPECT_TRUE(
RectNear(contents_coverage.value(),
495 CalculateSigmaForBlurRadius(radius,
Matrix());
496 ASSERT_TRUE(derived_sigma.
ok());
497 EXPECT_NEAR(sigma, derived_sigma.
value(), 0.01f);
513 EXPECT_FLOAT_EQ(tally, 1.0f);
516 for (
int i = 0;
i < 4; ++
i) {
552 GaussianBlurPipeline::FragmentShader::KernelSamples blur_info =
554 EXPECT_EQ(blur_info.sample_count, 3);
562 Point(-1.3333333, 0));
563 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[0]), 0.3);
566 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[1]), 0.4);
569 EXPECT_FLOAT_EQ(GetCoefficient(blur_info.sample_data[2]), 0.3);
582 Scalar fract = fabsf(modf(point.
x, &int_part));
584 return left * fract + right * (1.0 - fract);
586 return left * (1.0 - fract) + right * fract;
590 lerp(GetUVOffset(blur_info.sample_data[0]),
data[0],
data[1]) *
591 GetCoefficient(blur_info.sample_data[0]) +
592 data[2] * GetCoefficient(blur_info.sample_data[1]) +
593 lerp(GetUVOffset(blur_info.sample_data[2]),
data[3],
data[4]) *
594 GetCoefficient(blur_info.sample_data[2]);
596 EXPECT_NEAR(original_output, fast_output, 0.01);
609 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
611 EXPECT_EQ(fast_kernel_samples.sample_count, 17);
614 for (
int i = 0;
i < 33;
i++) {
623 Scalar fract = fabsf(modf(point.x, &fint_part));
625 int32_t int_part =
static_cast<int32_t
>(fint_part) + 16;
626 return data[int_part];
628 int32_t left =
static_cast<int32_t
>(floor(point.x)) + 16;
629 int32_t right =
static_cast<int32_t
>(ceil(point.x)) + 16;
631 return fract *
data[left] + (1.0 - fract) *
data[right];
633 return (1.0 - fract) *
data[left] + fract *
data[right];
640 auto sample = kernel_samples.
samples[
i];
641 output += sample.
coefficient * sampler(sample.uv_offset);
645 for (
int i = 0;
i < fast_kernel_samples.sample_count;
i++) {
646 fast_output += GetCoefficient(fast_kernel_samples.sample_data[
i]) *
647 sampler(GetUVOffset(fast_kernel_samples.sample_data[
i]));
650 EXPECT_NEAR(output, fast_output, 0.1);
662 GaussianBlurPipeline::FragmentShader::KernelSamples frag_kernel_samples =
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
std::shared_ptr< ContentContext > GetContentContext() const
@ kNormal
Blurred inside and outside.
Performs a bidirectional Gaussian blur.
static Scalar CalculateBlurRadius(Scalar sigma)
static Scalar ScaleSigma(Scalar sigma)
std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const override
Internal utility method for |GetLocalCoverage| that computes the output coverage of this filter acros...
static Scalar CalculateScale(Scalar sigma)
static Quad CalculateUVs(const std::shared_ptr< FilterInput > &filter_input, const Entity &entity, const Rect &source_rect, const ISize &texture_size)
std::shared_ptr< Context > GetContext() const
Render passes encode render commands directed as one specific render target into an underlying comman...
std::shared_ptr< Texture > MakeTexture(ISize size)
Create a texture that has been cleared to transparent black.
#define FML_CHECK(condition)
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Vector2 scaled_sigma
Sigma when considering an entity's scale and the effect transform.
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
#define EXPECT_RECT_NEAR(a, b)
#define EXPECT_POINT_NEAR(a, b)
TEST(FrameTimingsRecorderTest, RecordVsync)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
TEST_P(AiksTest, DrawAtlasNoColor)
static constexpr int32_t kGaussianBlurMaxKernelSize
KernelSamples GenerateBlurInfo(BlurParameters parameters)
std::array< Point, 4 > Quad
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
KernelSample samples[kMaxKernelSize]
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
static constexpr TRect MakeSize(const TSize< U > &size)
static constexpr std::optional< TRect > MakePointBounds(const U &value)
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)