Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2750,7 +2750,7 @@ TEST_P(AiksTest, CanRenderClippedBlur) {
.color = Color::Green(),
.image_filter = ImageFilter::MakeBlur(
Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp),
Entity::TileMode::kDecal),
});
canvas.Restore();

Expand Down Expand Up @@ -3960,6 +3960,48 @@ TEST_P(AiksTest, GaussianBlurMipMapImageFilter) {
#endif
}

TEST_P(AiksTest, GaussianBlurMipMapSolidColor) {
size_t blur_required_mip_count =
GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
fml::testing::LogCapture log_capture;
Canvas canvas;
canvas.DrawPath(PathBuilder{}
.MoveTo({100, 100})
.LineTo({200, 100})
.LineTo({150, 200})
.LineTo({50, 200})
.Close()
.TakePath(),
{.color = Color::Chartreuse(),
.image_filter = ImageFilter::MakeBlur(
Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp)});

Picture picture = canvas.EndRecordingAsPicture();
std::shared_ptr<RenderTargetCache> cache =
std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
AiksContext aiks_context(GetContext(), nullptr, cache);
picture.ToImage(aiks_context, {1024, 768});

size_t max_mip_count = 0;
for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd();
++it) {
max_mip_count =
std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count);
}
EXPECT_EQ(max_mip_count, blur_required_mip_count);
// The log is FML_DLOG, so only check in debug builds.
#ifndef NDEBUG
if (GetParam() != PlaygroundBackend::kOpenGLES) {
EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
std::string::npos);
} else {
EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
std::string::npos);
}
#endif
}

TEST_P(AiksTest, ImageColorSourceEffectTransform) {
// Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885

Expand Down
3 changes: 2 additions & 1 deletion impeller/display_list/dl_image_impeller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ sk_sp<DlImageImpeller> DlImageImpeller::MakeFromYUVTextures(
std::nullopt, // coverage_limit
std::nullopt, // sampler_descriptor
true, // msaa_enabled
"MakeYUVToRGBFilter Snapshot"); // label
/*mip_count=*/1,
"MakeYUVToRGBFilter Snapshot"); // label
if (!snapshot.has_value()) {
return nullptr;
}
Expand Down
1 change: 1 addition & 0 deletions impeller/entity/contents/atlas_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ bool AtlasContents::Render(const ContentContext& renderer,
std::nullopt, // coverage_limit
std::nullopt, // sampler_descriptor
true, // msaa_enabled
/*mip_count=*/1,
"AtlasContents Snapshot"); // label
if (!snapshot.has_value()) {
return false;
Expand Down
28 changes: 22 additions & 6 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "impeller/renderer/pipeline_descriptor.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_target.h"
#include "impeller/renderer/texture_mipmap.h"
#include "impeller/tessellator/tessellator.h"
#include "impeller/typographer/typographer_context.h"

Expand Down Expand Up @@ -429,20 +430,21 @@ fml::StatusOr<RenderTarget> ContentContext::MakeSubpass(
const std::string& label,
ISize texture_size,
const SubpassCallback& subpass_callback,
bool msaa_enabled) const {
bool msaa_enabled,
int32_t mip_count) const {
const std::shared_ptr<Context>& context = GetContext();
RenderTarget subpass_target;
if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) {
subpass_target = RenderTarget::CreateOffscreenMSAA(
*context, *GetRenderTargetCache(), texture_size, /*mip_count=*/1,
SPrintF("%s Offscreen", label.c_str()),
*context, *GetRenderTargetCache(), texture_size,
/*mip_count=*/mip_count, SPrintF("%s Offscreen", label.c_str()),
RenderTarget::kDefaultColorAttachmentConfigMSAA,
std::nullopt // stencil_attachment_config
);
} else {
subpass_target = RenderTarget::CreateOffscreen(
*context, *GetRenderTargetCache(), texture_size, /*mip_count=*/1,
SPrintF("%s Offscreen", label.c_str()),
*context, *GetRenderTargetCache(), texture_size,
/*mip_count=*/mip_count, SPrintF("%s Offscreen", label.c_str()),
RenderTarget::kDefaultColorAttachmentConfig, //
std::nullopt // stencil_attachment_config
);
Expand Down Expand Up @@ -477,7 +479,21 @@ fml::StatusOr<RenderTarget> ContentContext::MakeSubpass(
return fml::Status(fml::StatusCode::kUnknown, "");
}

if (!sub_command_buffer->EncodeAndSubmit(sub_renderpass)) {
if (!sub_renderpass->EncodeCommands()) {
return fml::Status(fml::StatusCode::kUnknown, "");
}

const std::shared_ptr<Texture>& target_texture =
subpass_target.GetRenderTargetTexture();
if (target_texture->GetMipCount() > 1) {
fml::Status mipmap_status =
AddMipmapGeneration(sub_command_buffer, context, target_texture);
if (!mipmap_status.ok()) {
return mipmap_status;
}
}

if (!sub_command_buffer->SubmitCommands()) {
return fml::Status(fml::StatusCode::kUnknown, "");
}

Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/content_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,8 @@ class ContentContext {
const std::string& label,
ISize texture_size,
const SubpassCallback& subpass_callback,
bool msaa_enabled = true) const;
bool msaa_enabled = true,
int32_t mip_count = 1) const;

/// Makes a subpass that will render to `subpass_target`.
fml::StatusOr<RenderTarget> MakeSubpass(
Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
std::optional<Rect> coverage_limit,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled,
int32_t mip_count,
const std::string& label) const {
auto coverage = GetCoverage(entity);
if (!coverage.has_value()) {
Expand Down Expand Up @@ -90,7 +91,7 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
entity.GetTransform());
return contents.Render(renderer, sub_entity, pass);
},
msaa_enabled);
msaa_enabled, mip_count);

if (!render_target.ok()) {
return std::nullopt;
Expand Down
1 change: 1 addition & 0 deletions impeller/entity/contents/contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class Contents {
std::optional<Rect> coverage_limit = std::nullopt,
const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
bool msaa_enabled = true,
int32_t mip_count = 1,
const std::string& label = "Snapshot") const;

virtual bool ShouldRender(const Entity& entity,
Expand Down
7 changes: 5 additions & 2 deletions impeller/entity/contents/filters/filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
return blur;
}

const int32_t FilterContents::kBlurFilterRequiredMipCount = 4;
const int32_t FilterContents::kBlurFilterRequiredMipCount =
GaussianBlurFilterContents::kBlurFilterRequiredMipCount;

std::shared_ptr<FilterContents> FilterContents::MakeGaussianBlur(
const FilterInput::Ref& input,
Expand Down Expand Up @@ -262,6 +263,7 @@ std::optional<Snapshot> FilterContents::RenderToSnapshot(
std::optional<Rect> coverage_limit,
const std::optional<SamplerDescriptor>& sampler_descriptor,
bool msaa_enabled,
int32_t mip_count,
const std::string& label) const {
// Resolve the render instruction (entity) from the filter and render it to a
// snapshot.
Expand All @@ -274,7 +276,8 @@ std::optional<Snapshot> FilterContents::RenderToSnapshot(
coverage_limit, // coverage_limit
std::nullopt, // sampler_descriptor
true, // msaa_enabled
label); // label
/*mip_count=*/mip_count,
label); // label
}

return std::nullopt;
Expand Down
1 change: 1 addition & 0 deletions impeller/entity/contents/filters/filter_contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class FilterContents : public Contents {
std::optional<Rect> coverage_limit = std::nullopt,
const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
bool msaa_enabled = true,
int32_t mip_count = 1,
const std::string& label = "Filter Snapshot") const override;

// |Contents|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace impeller {
using GaussianBlurVertexShader = KernelPipeline::VertexShader;
using GaussianBlurFragmentShader = KernelPipeline::FragmentShader;

const int32_t GaussianBlurFilterContents::kBlurFilterRequiredMipCount = 4;

namespace {

SamplerDescriptor MakeSamplerDescriptor(MinMagFilter filter,
Expand Down Expand Up @@ -269,9 +271,18 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
expanded_coverage_hint = coverage_hint->Expand(local_padding);
}

int32_t mip_count = kBlurFilterRequiredMipCount;
if (renderer.GetContext()->GetBackendType() ==
Context::BackendType::kOpenGLES) {
// TODO(https://github.com/flutter/flutter/issues/141732): Implement mip map
// generation on opengles.
mip_count = 1;
}

std::optional<Snapshot> input_snapshot =
inputs[0]->GetSnapshot("GaussianBlur", renderer, entity,
/*coverage_limit=*/expanded_coverage_hint);
/*coverage_limit=*/expanded_coverage_hint,
/*mip_count=*/mip_count);
if (!input_snapshot.has_value()) {
return std::nullopt;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ KernelPipeline::FragmentShader::KernelSamples GenerateBlurInfo(
class GaussianBlurFilterContents final : public FilterContents {
public:
static std::string_view kNoMipsError;
static const int32_t kBlurFilterRequiredMipCount;

explicit GaussianBlurFilterContents(Scalar sigma_x,
Scalar sigma_y,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ std::optional<Snapshot> ContentsFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const {
std::optional<Rect> coverage_limit,
int32_t mip_count) const {
if (!coverage_limit.has_value() && entity.GetContents()) {
coverage_limit = entity.GetContents()->GetCoverageHint();
}
Expand All @@ -36,6 +37,7 @@ std::optional<Snapshot> ContentsFilterInput::GetSnapshot(
coverage_limit, // coverage_limit
std::nullopt, // sampler_descriptor
msaa_enabled_, // msaa_enabled
/*mip_count=*/mip_count,
SPrintF("Contents to %s Filter Snapshot", label.c_str())); // label
}
return snapshot_;
Expand Down
10 changes: 5 additions & 5 deletions impeller/entity/contents/filters/inputs/contents_filter_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ class ContentsFilterInput final : public FilterInput {
Variant GetInput() const override;

// |FilterInput|
std::optional<Snapshot> GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const override;
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit,
int32_t mip_count) const override;

// |FilterInput|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ std::optional<Snapshot> FilterContentsFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const {
std::optional<Rect> coverage_limit,
int32_t mip_count) const {
if (!snapshot_.has_value()) {
snapshot_ = filter_->RenderToSnapshot(
renderer, // renderer
entity, // entity
coverage_limit, // coverage_limit
std::nullopt, // sampler_descriptor
true, // msaa_enabled
/*mip_count=*/mip_count,
SPrintF("Filter to %s Filter Snapshot", label.c_str())); // label
}
return snapshot_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ class FilterContentsFilterInput final : public FilterInput {
Variant GetInput() const override;

// |FilterInput|
std::optional<Snapshot> GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const override;
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit,
int32_t mip_count) const override;

// |FilterInput|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/filters/inputs/filter_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ class FilterInput {
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit = std::nullopt) const = 0;
std::optional<Rect> coverage_limit = std::nullopt,
int32_t mip_count = 1) const = 0;

std::optional<Rect> GetLocalCoverage(const Entity& entity) const;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ std::optional<Snapshot> PlaceholderFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const {
std::optional<Rect> coverage_limit,
int32_t mip_count) const {
return std::nullopt;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ class PlaceholderFilterInput final : public FilterInput {
Variant GetInput() const override;

// |FilterInput|
std::optional<Snapshot> GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const override;
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit,
int32_t mip_count = 1) const override;

// |FilterInput|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ std::optional<Snapshot> TextureFilterInput::GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const {
std::optional<Rect> coverage_limit,
int32_t mip_count) const {
auto snapshot =
Snapshot{.texture = texture_, .transform = GetTransform(entity)};
if (texture_->GetMipCount() > 1) {
Expand Down
10 changes: 5 additions & 5 deletions impeller/entity/contents/filters/inputs/texture_filter_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ class TextureFilterInput final : public FilterInput {
Variant GetInput() const override;

// |FilterInput|
std::optional<Snapshot> GetSnapshot(
const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit) const override;
std::optional<Snapshot> GetSnapshot(const std::string& label,
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit,
int32_t mip_count) const override;

// |FilterInput|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
Expand Down
3 changes: 2 additions & 1 deletion impeller/entity/contents/framebuffer_blend_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer,
Rect::MakeSize(pass.GetRenderTargetSize()), // coverage_limit
std::nullopt, // sampler_descriptor
true, // msaa_enabled
"FramebufferBlendContents Snapshot"); // label
/*mip_count=*/1,
"FramebufferBlendContents Snapshot"); // label

if (!src_snapshot.has_value()) {
return true;
Expand Down
Loading