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 4 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
74 changes: 74 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 @@ -2441,6 +2443,78 @@ 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(GetContentScale()));
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));

EXPECT_EQ(test_allocator->GetDescriptors().size(), 6u);
// Onscreen render target.
EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));

// Offscreen rect render target.
EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(200, 200));

// Advanced blend render target.
EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(200, 200));
EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
}

} // namespace testing
} // namespace impeller

Expand Down