Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] Dont blow away coverage hint on advanced blends. #46219

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
9 changes: 6 additions & 3 deletions impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,19 @@ static std::unique_ptr<PipelineT> CreateDefaultPipeline(

ContentContext::ContentContext(
std::shared_ptr<Context> context,
std::shared_ptr<TypographerContext> typographer_context)
std::shared_ptr<TypographerContext> typographer_context,
std::shared_ptr<RenderTargetAllocator> render_target_allocator)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change allows tests to provide their own RenderTargetAllocator implementation, which I use to introspect into texture allocation.

: context_(std::move(context)),
lazy_glyph_atlas_(
std::make_shared<LazyGlyphAtlas>(std::move(typographer_context))),
tessellator_(std::make_shared<Tessellator>()),
#if IMPELLER_ENABLE_3D
scene_context_(std::make_shared<scene::SceneContext>(context_)),
#endif // IMPELLER_ENABLE_3D
render_target_cache_(std::make_shared<RenderTargetCache>(
context_->GetResourceAllocator())) {
render_target_cache_(render_target_allocator == nullptr
? std::make_shared<RenderTargetCache>(
context_->GetResourceAllocator())
: std::move(render_target_allocator)) {
if (!context_ || !context_->IsValid()) {
return;
}
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 @@ -343,7 +343,8 @@ class ContentContext {
public:
explicit ContentContext(
std::shared_ptr<Context> context,
std::shared_ptr<TypographerContext> typographer_context);
std::shared_ptr<TypographerContext> typographer_context,
std::shared_ptr<RenderTargetAllocator> render_target_allocator = nullptr);

~ContentContext();

Expand Down
11 changes: 10 additions & 1 deletion impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,16 @@ bool EntityPass::OnRender(
// rendered output will actually be used, and so we set this to the current
// stencil coverage (which is the max clip bounds). The contents may
// optionally use this hint to avoid unnecessary rendering work.
element_entity.GetContents()->SetCoverageHint(current_stencil_coverage);
if (element_entity.GetContents()->GetCoverageHint().has_value()) {
// If the element already has a coverage hint (because its an advanced
// blend), then we need to intersect the stencil coverage hint with the
// existing coverage hint.
element_entity.GetContents()->SetCoverageHint(
current_stencil_coverage->Intersection(
element_entity.GetContents()->GetCoverageHint().value()));
} else {
element_entity.GetContents()->SetCoverageHint(current_stencil_coverage);
}

switch (stencil_coverage.type) {
case Contents::StencilCoverage::Type::kNoChange:
Expand Down
86 changes: 86 additions & 0 deletions impeller/entity/entity_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
#include <memory>
#include <optional>
#include <unordered_map>
#include <utility>
#include <vector>

#include "flutter/testing/testing.h"
#include "fml/logging.h"
#include "fml/time/time_point.h"
#include "gtest/gtest.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/entity/contents/atlas_contents.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/conical_gradient_contents.h"
Expand Down Expand Up @@ -42,6 +44,7 @@
#include "impeller/geometry/geometry_asserts.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/sigma.h"
#include "impeller/geometry/vector.h"
#include "impeller/playground/playground.h"
#include "impeller/playground/widgets.h"
#include "impeller/renderer/command.h"
Expand Down Expand Up @@ -2441,6 +2444,89 @@ TEST_P(EntityTest, TextContentsCeilsGlyphScaleToDecimal) {
ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
}

class TestRenderTargetAllocator : public RenderTargetAllocator {
public:
explicit TestRenderTargetAllocator(std::shared_ptr<Allocator> allocator)
: RenderTargetAllocator(std::move(allocator)) {}

~TestRenderTargetAllocator() = default;

std::shared_ptr<Texture> CreateTexture(
const TextureDescriptor& desc) override {
allocated_.push_back(desc);
return RenderTargetAllocator::CreateTexture(desc);
}

void Start() override { RenderTargetAllocator::Start(); }

void End() override { RenderTargetAllocator::End(); }

std::vector<TextureDescriptor> GetDescriptors() const { return allocated_; }

private:
std::vector<TextureDescriptor> allocated_;
};

TEST_P(EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass) {
if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
"for advanced blends.";
}

auto contents = std::make_shared<SolidColorContents>();
contents->SetGeometry(Geometry::MakeRect({100, 100, 100, 100}));
contents->SetColor(Color::Red());

Entity entity;
entity.SetTransformation(Matrix::MakeScale(Vector3(2, 2, 1)));
entity.SetBlendMode(BlendMode::kColorBurn);
entity.SetContents(contents);

auto coverage = entity.GetCoverage();
EXPECT_TRUE(coverage.has_value());

auto pass = std::make_unique<EntityPass>();
auto test_allocator = std::make_shared<TestRenderTargetAllocator>(
GetContext()->GetResourceAllocator());
auto stencil_config = RenderTarget::AttachmentConfig{
.storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kDontCare,
.clear_color = Color::BlackTransparent()};
auto rt = RenderTarget::CreateOffscreen(
*GetContext(), *test_allocator, ISize::MakeWH(1000, 1000), "Offscreen",
RenderTarget::kDefaultColorAttachmentConfig, stencil_config);
auto content_context = ContentContext(
GetContext(), TypographerContextSkia::Make(), test_allocator);
pass->AddEntity(entity);

EXPECT_TRUE(pass->Render(content_context, rt));

if (test_allocator->GetDescriptors().size() == 6u) {
EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));

EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
} else if (test_allocator->GetDescriptors().size() == 9u) {
// Onscreen render target.
EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));
EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(1000, 1000));
EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(1000, 1000));
EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(1000, 1000));

EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[6].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[7].size, ISize(200, 200));
} else {
EXPECT_TRUE(false);
}
}

} // namespace testing
} // namespace impeller

Expand Down