Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit abb7571

Browse files
committed
Refactor into separate TU and add tests.
1 parent 618fd2a commit abb7571

File tree

8 files changed

+280
-111
lines changed

8 files changed

+280
-111
lines changed

ci/licenses_golden/excluded_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
../../../flutter/impeller/entity/contents/host_buffer_unittests.cc
163163
../../../flutter/impeller/entity/contents/test
164164
../../../flutter/impeller/entity/contents/tiled_texture_contents_unittests.cc
165+
../../../flutter/impeller/entity/draw_order_resolver_unittests.cc
165166
../../../flutter/impeller/entity/entity_pass_target_unittests.cc
166167
../../../flutter/impeller/entity/entity_pass_unittests.cc
167168
../../../flutter/impeller/entity/entity_unittests.cc

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42128,6 +42128,8 @@ ORIGIN: ../../../flutter/impeller/entity/contents/tiled_texture_contents.cc + ..
4212842128
ORIGIN: ../../../flutter/impeller/entity/contents/tiled_texture_contents.h + ../../../flutter/LICENSE
4212942129
ORIGIN: ../../../flutter/impeller/entity/contents/vertices_contents.cc + ../../../flutter/LICENSE
4213042130
ORIGIN: ../../../flutter/impeller/entity/contents/vertices_contents.h + ../../../flutter/LICENSE
42131+
ORIGIN: ../../../flutter/impeller/entity/draw_order_resolver.cc + ../../../flutter/LICENSE
42132+
ORIGIN: ../../../flutter/impeller/entity/draw_order_resolver.h + ../../../flutter/LICENSE
4213142133
ORIGIN: ../../../flutter/impeller/entity/entity.cc + ../../../flutter/LICENSE
4213242134
ORIGIN: ../../../flutter/impeller/entity/entity.h + ../../../flutter/LICENSE
4213342135
ORIGIN: ../../../flutter/impeller/entity/entity_pass.cc + ../../../flutter/LICENSE
@@ -45010,6 +45012,8 @@ FILE: ../../../flutter/impeller/entity/contents/tiled_texture_contents.cc
4501045012
FILE: ../../../flutter/impeller/entity/contents/tiled_texture_contents.h
4501145013
FILE: ../../../flutter/impeller/entity/contents/vertices_contents.cc
4501245014
FILE: ../../../flutter/impeller/entity/contents/vertices_contents.h
45015+
FILE: ../../../flutter/impeller/entity/draw_order_resolver.cc
45016+
FILE: ../../../flutter/impeller/entity/draw_order_resolver.h
4501345017
FILE: ../../../flutter/impeller/entity/entity.cc
4501445018
FILE: ../../../flutter/impeller/entity/entity.h
4501545019
FILE: ../../../flutter/impeller/entity/entity_pass.cc

impeller/entity/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ impeller_component("entity") {
166166
"contents/tiled_texture_contents.h",
167167
"contents/vertices_contents.cc",
168168
"contents/vertices_contents.h",
169+
"draw_order_resolver.cc",
170+
"draw_order_resolver.h",
169171
"entity.cc",
170172
"entity.h",
171173
"entity_pass.cc",
@@ -248,6 +250,7 @@ impeller_component("entity_unittests") {
248250
"contents/filters/matrix_filter_contents_unittests.cc",
249251
"contents/host_buffer_unittests.cc",
250252
"contents/tiled_texture_contents_unittests.cc",
253+
"draw_order_resolver_unittests.cc",
251254
"entity_pass_target_unittests.cc",
252255
"entity_pass_unittests.cc",
253256
"entity_playground.cc",
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "impeller/entity/draw_order_resolver.h"
6+
7+
#include "flutter/fml/logging.h"
8+
#include "impeller/base/validation.h"
9+
10+
namespace impeller {
11+
12+
DrawOrderResolver::DrawOrderResolver() : draw_order_layers_({{}}){};
13+
14+
void DrawOrderResolver::AddElement(size_t element_index, bool is_opaque) {
15+
DrawOrderLayer& layer = draw_order_layers_.back();
16+
if (is_opaque) {
17+
layer.opaque_elements.push_back(element_index);
18+
} else {
19+
layer.dependent_elements.push_back(element_index);
20+
}
21+
}
22+
void DrawOrderResolver::PushClip(size_t element_index) {
23+
draw_order_layers_.back().dependent_elements.push_back(element_index);
24+
draw_order_layers_.push_back({});
25+
};
26+
27+
void DrawOrderResolver::PopClip() {
28+
if (draw_order_layers_.size() == 1u) {
29+
// This is likely recoverable, so don't assert.
30+
VALIDATION_LOG
31+
<< "Attemped to pop the root draw order layer. This is a bug in "
32+
"`EntityPass`.";
33+
return;
34+
}
35+
36+
DrawOrderLayer& layer = draw_order_layers_.back();
37+
DrawOrderLayer& parent_layer =
38+
draw_order_layers_[draw_order_layers_.size() - 2];
39+
40+
layer.WriteCombinedDraws(parent_layer.dependent_elements, 0, 0);
41+
42+
draw_order_layers_.pop_back();
43+
}
44+
45+
DrawOrderResolver::ElementRefs DrawOrderResolver::GetSortedDraws(
46+
size_t opaque_skip_count,
47+
size_t translucent_skip_count) const {
48+
FML_DCHECK(draw_order_layers_.size() == 1u);
49+
50+
ElementRefs sorted_elements;
51+
draw_order_layers_.back().WriteCombinedDraws(
52+
sorted_elements, opaque_skip_count, translucent_skip_count);
53+
54+
return sorted_elements;
55+
}
56+
57+
void DrawOrderResolver::DrawOrderLayer::WriteCombinedDraws(
58+
ElementRefs& destination,
59+
size_t opaque_skip_count,
60+
size_t translucent_skip_count) const {
61+
FML_DCHECK(opaque_skip_count <= opaque_elements.size());
62+
FML_DCHECK(translucent_skip_count <= dependent_elements.size());
63+
64+
destination.reserve(destination.size() + //
65+
opaque_elements.size() - opaque_skip_count + //
66+
dependent_elements.size());
67+
68+
// Draw backdrop-independent elements first.
69+
destination.insert(destination.end(), opaque_elements.rbegin(),
70+
opaque_elements.rend() - opaque_skip_count);
71+
// Then, draw backdrop-dependent elements in their original order.
72+
destination.insert(destination.end(),
73+
dependent_elements.begin() + translucent_skip_count,
74+
dependent_elements.end());
75+
}
76+
77+
} // namespace impeller

impeller/entity/draw_order_resolver.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_IMPELLER_ENTITY_DRAW_ORDER_RESOLVER_H_
6+
#define FLUTTER_IMPELLER_ENTITY_DRAW_ORDER_RESOLVER_H_
7+
8+
#include <vector>
9+
10+
namespace impeller {
11+
12+
/// @brief Produces an optimized draw order for a draw list given in painter's
13+
/// order.
14+
class DrawOrderResolver {
15+
public:
16+
using ElementRefs = std::vector<size_t>;
17+
18+
DrawOrderResolver();
19+
20+
void AddElement(size_t element_index, bool is_opaque);
21+
22+
void PushClip(size_t element_index);
23+
24+
void PopClip();
25+
26+
//-------------------------------------------------------------------------
27+
/// @brief Returns the sorted draws for the current draw order layer.
28+
/// This should only be called after all recording has finished.
29+
///
30+
/// @param[in] opaque_skip_count The number of opaque elements to skip
31+
/// when appending the combined elements.
32+
/// This is used for the "clear color"
33+
/// optimization.
34+
///
35+
ElementRefs GetSortedDraws(size_t opaque_skip_count,
36+
size_t translucent_skip_count) const;
37+
38+
private:
39+
/// A data structure for collecting sorted draws for a given "draw order
40+
/// layer". Currently these layers just correspond to the local clip stack
41+
/// corresponds to the clip stack.
42+
struct DrawOrderLayer {
43+
/// The list of backdrop-independent elements (always just opaque). These
44+
/// are order independent, and so we draw them optimally render these
45+
/// elements in reverse painter's order so that they cull one another
46+
ElementRefs opaque_elements;
47+
48+
/// The list of backdrop-dependent elements with respect to this draw
49+
/// order layer. These elements are drawn after all of the independent
50+
/// elements.
51+
/// The elements of all child draw layers will be resolved to this list.
52+
ElementRefs dependent_elements;
53+
54+
//-----------------------------------------------------------------------
55+
/// @brief Appends the combined opaque and transparent elements into
56+
/// a final destination buffer.
57+
///
58+
/// @param[in] destination The buffer to append the combined
59+
/// elements to.
60+
/// @param[in] opaque_skip_count The number of opaque elements to skip
61+
/// when appending the combined elements.
62+
/// This is used for the "clear color"
63+
/// optimization.
64+
///
65+
void WriteCombinedDraws(ElementRefs& destination,
66+
size_t opaque_skip_count,
67+
size_t translucent_skip_count) const;
68+
};
69+
std::vector<DrawOrderLayer> draw_order_layers_;
70+
71+
DrawOrderResolver(const DrawOrderResolver&) = delete;
72+
73+
DrawOrderResolver& operator=(const DrawOrderResolver&) = delete;
74+
};
75+
76+
} // namespace impeller
77+
78+
#endif // FLUTTER_IMPELLER_ENTITY_DRAW_ORDER_RESOLVER_H_
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/testing/testing.h"
6+
#include "impeller/entity/draw_order_resolver.h"
7+
#include "third_party/googletest/googletest/include/gtest/gtest.h"
8+
9+
namespace impeller {
10+
namespace testing {
11+
12+
TEST(DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithNoClips) {
13+
DrawOrderResolver resolver;
14+
15+
// Opaque items.
16+
resolver.AddElement(0, true);
17+
resolver.AddElement(1, true);
18+
// Translucent items.
19+
resolver.AddElement(2, false);
20+
resolver.AddElement(3, false);
21+
22+
auto sorted_elements = resolver.GetSortedDraws(0, 0);
23+
24+
EXPECT_EQ(sorted_elements.size(), 4u);
25+
// First, the opaque items are drawn in reverse order.
26+
EXPECT_EQ(sorted_elements[0], 1u);
27+
EXPECT_EQ(sorted_elements[1], 0u);
28+
// Then the translucent items are drawn.
29+
EXPECT_EQ(sorted_elements[2], 3u);
30+
EXPECT_EQ(sorted_elements[3], 2u);
31+
}
32+
33+
TEST(DrawOrderResolverTest, GetSortedDrawsReturnsCorrectOrderWithClips) {
34+
DrawOrderResolver resolver;
35+
36+
// Items before clip.
37+
resolver.AddElement(0, false);
38+
resolver.AddElement(1, true);
39+
resolver.AddElement(2, false);
40+
resolver.AddElement(3, true);
41+
42+
// Clip.
43+
resolver.PushClip(4);
44+
{
45+
// Clipped items.
46+
resolver.AddElement(5, false);
47+
resolver.AddElement(6, false);
48+
// Clipped translucent items.
49+
resolver.AddElement(7, true);
50+
resolver.AddElement(8, true);
51+
}
52+
resolver.PopClip();
53+
54+
// Items after clip.
55+
resolver.AddElement(9, true);
56+
resolver.AddElement(10, false);
57+
resolver.AddElement(11, true);
58+
resolver.AddElement(12, false);
59+
60+
auto sorted_elements = resolver.GetSortedDraws(0, 0);
61+
62+
EXPECT_EQ(sorted_elements.size(), 13u);
63+
// First, all the non-clipped opaque items are drawn in reverse order.
64+
EXPECT_EQ(sorted_elements[0], 11u);
65+
EXPECT_EQ(sorted_elements[1], 9u);
66+
EXPECT_EQ(sorted_elements[2], 3u);
67+
EXPECT_EQ(sorted_elements[3], 1u);
68+
// Then, the clip is drawn.
69+
EXPECT_EQ(sorted_elements[4], 4u);
70+
{
71+
// Opaque clipped items are drawn in reverse order.
72+
EXPECT_EQ(sorted_elements[5], 8u);
73+
EXPECT_EQ(sorted_elements[6], 7u);
74+
// Translucent clipped items are drawn.
75+
EXPECT_EQ(sorted_elements[7], 5u);
76+
EXPECT_EQ(sorted_elements[8], 6u);
77+
}
78+
// Finally, the non-clipped translucent items are drawn in their original
79+
// order.
80+
EXPECT_EQ(sorted_elements[9], 0u);
81+
EXPECT_EQ(sorted_elements[10], 2u);
82+
EXPECT_EQ(sorted_elements[11], 10u);
83+
EXPECT_EQ(sorted_elements[12], 12u);
84+
}
85+
86+
TEST(DrawOrderResolverTest, GetSortedDrawsRespectsSkipCounts) {
87+
DrawOrderResolver resolver;
88+
89+
// These items will be skipped.
90+
resolver.AddElement(0, false);
91+
resolver.AddElement(1, true);
92+
resolver.AddElement(2, false);
93+
// These ones will be included in the final draw list.
94+
resolver.AddElement(3, false);
95+
resolver.AddElement(4, true);
96+
resolver.AddElement(5, true);
97+
98+
// Form the draw list, skipping elements 0, 1, and 2.
99+
// This emulates what happens when entitypass applies the clear color
100+
// optimization.
101+
auto sorted_elements = resolver.GetSortedDraws(1, 2);
102+
103+
EXPECT_EQ(sorted_elements.size(), 4u);
104+
// First, opaque items are drawn in reverse order.
105+
EXPECT_EQ(sorted_elements[0], 5u);
106+
EXPECT_EQ(sorted_elements[1], 4u);
107+
// Then, translucent items are drawn.
108+
EXPECT_EQ(sorted_elements[2], 3u);
109+
}
110+
111+
} // namespace testing
112+
} // namespace impeller

impeller/entity/entity_pass.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "impeller/entity/contents/filters/inputs/filter_input.h"
2121
#include "impeller/entity/contents/framebuffer_blend_contents.h"
2222
#include "impeller/entity/contents/texture_contents.h"
23+
#include "impeller/entity/draw_order_resolver.h"
2324
#include "impeller/entity/entity.h"
2425
#include "impeller/entity/entity_pass_clip_stack.h"
2526
#include "impeller/entity/inline_pass_context.h"
@@ -923,8 +924,9 @@ bool EntityPass::OnRender(
923924
}
924925
}
925926

926-
ElementRefs sorted_elements = draw_order_resolver_.GetSortedDraws(
927-
opaque_clear_entity_count, translucent_clear_entity_count);
927+
DrawOrderResolver::ElementRefs sorted_elements =
928+
draw_order_resolver_.GetSortedDraws(opaque_clear_entity_count,
929+
translucent_clear_entity_count);
928930
for (const auto& element_ref : sorted_elements) {
929931
const Element& element = elements_[element_ref];
930932

0 commit comments

Comments
 (0)