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
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
Contributor 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