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 1 commit
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
1 change: 1 addition & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ impeller_component("entity_unittests") {

sources = [
"contents/checkerboard_contents_unittests.cc",
"contents/clip_contents_unittests.cc",
"contents/content_context_unittests.cc",
"contents/filters/gaussian_blur_filter_contents_unittests.cc",
"contents/filters/inputs/filter_input_unittests.cc",
Expand Down
12 changes: 12 additions & 0 deletions impeller/entity/contents/clip_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ bool ClipContents::RenderDepthClip(const ContentContext& renderer,
const Geometry& geometry) const {
using VS = ClipPipeline::VertexShader;

if (clip_op == Entity::ClipOperation::kIntersect &&
geometry.IsAxisAlignedRect() &&
entity.GetTransform().IsTranslationScaleOnly()) {
std::optional<Rect> coverage = geometry.GetCoverage(entity.GetTransform());
if (coverage.has_value() &&
coverage->Contains(Rect::MakeSize(pass.GetRenderTargetSize()))) {
// Skip axis-aligned intersect clips that cover the whole render target
// since they won't draw anything to the depth buffer.
return true;
}
}

VS::FrameInfo info;
info.depth = GetShaderClipDepth(entity);

Expand Down
59 changes: 59 additions & 0 deletions impeller/entity/contents/clip_contents_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <optional>

#include "gtest/gtest.h"

#include "impeller/entity/contents/checkerboard_contents.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/test/recording_render_pass.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/entity_playground.h"
#include "impeller/renderer/render_target.h"

namespace impeller {
namespace testing {

using EntityTest = EntityPlayground;

TEST_P(EntityTest, ClipContentsOptimizesFullScreenIntersectClips) {
if (!ContentContext::kEnableStencilThenCover) {
GTEST_SKIP();
return;
}

// Set up mock environment.

auto content_context = GetContentContext();
auto buffer = content_context->GetContext()->CreateCommandBuffer();
auto render_target =
GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
*content_context->GetContext(), {100, 100},
/*mip_count=*/1);
auto render_pass = buffer->CreateRenderPass(render_target);
auto recording_pass = std::make_shared<RecordingRenderPass>(
render_pass, GetContext(), render_target);

// Set up clip contents.

auto contents = std::make_shared<ClipContents>();
contents->SetClipOperation(Entity::ClipOperation::kIntersect);
contents->SetGeometry(Geometry::MakeCover());

Entity entity;
entity.SetContents(std::move(contents));

// Render the clip contents.

ASSERT_TRUE(recording_pass->GetCommands().empty());
ASSERT_TRUE(entity.Render(*content_context, *recording_pass));
ASSERT_FALSE(recording_pass->GetCommands().empty());
}

} // namespace testing
} // namespace impeller