Mir

Merge lp:~afrantzis/mir/fix-1340078-occlusion into lp:mir

Proposed by Alexandros Frantzis
Status: Merged
Approved by: Alexandros Frantzis
Approved revision: no longer in the source branch.
Merged at revision: 1772
Proposed branch: lp:~afrantzis/mir/fix-1340078-occlusion
Merge into: lp:mir
Diff against target: 180 lines (+88/-9)
5 files modified
include/shared/mir/geometry/rectangle.h (+9/-0)
src/server/compositor/occlusion.cpp (+11/-8)
src/shared/geometry/rectangle.cpp (+14/-1)
tests/unit-tests/compositor/test_occlusion.cpp (+16/-0)
tests/unit-tests/geometry/test-rectangle.cpp (+38/-0)
To merge this branch: bzr merge lp:~afrantzis/mir/fix-1340078-occlusion
Reviewer Review Type Date Requested Status
Kevin DuBois (community) Approve
Alan Griffiths Approve
Alberto Aguirre (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+226261@code.launchpad.net

Commit message

compositor: Properly occlude partially on-screen surfaces (LP: #1340078)

Description of the change

compositor: Properly occlude partially on-screen surfaces

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

LGTM

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

23 + Rectangle intersection_with(Rectangle const& r) const;

Hmm, I would (slightly) prefer a free function for a symmetric operation. Vis:

Rectangle intersection_of(Rectangle const& l, Rectangle const& r);

PS
I thought briefly about operator&() but that gives an asymmetry with operator|().

review: Approve
Revision history for this message
Kevin DuBois (kdub) wrote :

okay

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/shared/mir/geometry/rectangle.h'
2--- include/shared/mir/geometry/rectangle.h 2014-04-23 18:51:37 +0000
3+++ include/shared/mir/geometry/rectangle.h 2014-07-10 09:06:31 +0000
4@@ -32,6 +32,13 @@
5
6 struct Rectangle
7 {
8+ Rectangle() = default;
9+
10+ Rectangle(Point const& top_left, Size const& size)
11+ : top_left{top_left}, size{size}
12+ {
13+ }
14+
15 Point top_left;
16 Size size;
17
18@@ -55,6 +62,8 @@
19 bool contains(Rectangle const& r) const;
20
21 bool overlaps(Rectangle const& r) const;
22+
23+ Rectangle intersection_with(Rectangle const& r) const;
24 };
25
26 inline bool operator == (Rectangle const& lhs, Rectangle const& rhs)
27
28=== modified file 'src/server/compositor/occlusion.cpp'
29--- src/server/compositor/occlusion.cpp 2014-06-23 17:19:22 +0000
30+++ src/server/compositor/occlusion.cpp 2014-07-10 09:06:31 +0000
31@@ -34,7 +34,9 @@
32 Rectangle const& area,
33 std::vector<Rectangle>& coverage)
34 {
35- static const glm::mat4 identity;
36+ static glm::mat4 const identity;
37+ static Rectangle const empty{};
38+
39 if (renderable.transformation() != identity)
40 return false; // Weirdly transformed. Assume never occluded.
41
42@@ -44,15 +46,16 @@
43 if (!renderable.visible())
44 return true; //invisible; definitely occluded.
45
46- // Not weirdly transformed but also not on this monitor? Don't care...
47- if (!area.overlaps(renderable.screen_position()))
48- return true; // Not on the display; definitely occluded.
49+ auto const& window = renderable.screen_position();
50+ auto const& clipped_window = window.intersection_with(area);
51+
52+ if (clipped_window == empty)
53+ return true; // Not in the area; definitely occluded.
54
55 bool occluded = false;
56- Rectangle const& window = renderable.screen_position();
57- for (const auto &r : coverage)
58+ for (auto const& r : coverage)
59 {
60- if (r.contains(window))
61+ if (r.contains(clipped_window))
62 {
63 occluded = true;
64 break;
65@@ -60,7 +63,7 @@
66 }
67
68 if (!occluded && renderable.alpha() == 1.0f && !renderable.shaped())
69- coverage.push_back(window);
70+ coverage.push_back(clipped_window);
71
72 return occluded;
73 }
74
75=== modified file 'src/shared/geometry/rectangle.cpp'
76--- src/shared/geometry/rectangle.cpp 2014-04-21 17:18:14 +0000
77+++ src/shared/geometry/rectangle.cpp 2014-07-10 09:06:31 +0000
78@@ -18,7 +18,7 @@
79
80 #include "mir/geometry/rectangle.h"
81
82-#include <cassert>
83+#include <algorithm>
84
85 namespace geom = mir::geometry;
86
87@@ -76,3 +76,16 @@
88 return false;
89 }
90 }
91+
92+geom::Rectangle geom::Rectangle::intersection_with(Rectangle const& r) const
93+{
94+ int const a = std::max(top_left.x.as_int(), r.top_left.x.as_int());
95+ int const b = std::min(bottom_right().x.as_int(), r.bottom_right().x.as_int());
96+ int const c = std::max(top_left.y.as_int(), r.top_left.y.as_int());
97+ int const d = std::min(bottom_right().y.as_int(), r.bottom_right().y.as_int());
98+
99+ if (a < b && c < d)
100+ return {{a, c}, {b - a, d - c}};
101+ else
102+ return geom::Rectangle();
103+}
104
105=== modified file 'tests/unit-tests/compositor/test_occlusion.cpp'
106--- tests/unit-tests/compositor/test_occlusion.cpp 2014-06-24 14:02:25 +0000
107+++ tests/unit-tests/compositor/test_occlusion.cpp 2014-07-10 09:06:31 +0000
108@@ -209,3 +209,19 @@
109 EXPECT_THAT(renderables_from(occlusions), ElementsAre(window3, window2, window1));
110 EXPECT_THAT(renderables_from(elements), ElementsAre(window5, window4, window0));
111 }
112+
113+TEST_F(OcclusionFilterTest,
114+ occludes_partially_onscreen_window_when_onscreen_part_is_covered_by_another_window)
115+{
116+ auto const partially_onscreen = std::make_shared<mtd::FakeRenderable>(-50, 100, 150, 100);
117+ auto const covering = std::make_shared<mtd::FakeRenderable>(0, 100, 100, 100);
118+ auto elements = scene_elements_from({
119+ partially_onscreen,
120+ covering
121+ });
122+
123+ auto const& occlusions = filter_occlusions_from(elements, monitor_rect);
124+
125+ EXPECT_THAT(renderables_from(occlusions), ElementsAre(partially_onscreen));
126+ EXPECT_THAT(renderables_from(elements), ElementsAre(covering));
127+}
128
129=== modified file 'tests/unit-tests/geometry/test-rectangle.cpp'
130--- tests/unit-tests/geometry/test-rectangle.cpp 2013-10-15 08:53:10 +0000
131+++ tests/unit-tests/geometry/test-rectangle.cpp 2014-07-10 09:06:31 +0000
132@@ -21,6 +21,8 @@
133 #include <gmock/gmock.h>
134 #include <gtest/gtest.h>
135
136+#include <vector>
137+
138 namespace geom = mir::geometry;
139
140 TEST(geometry, rectangle)
141@@ -195,3 +197,39 @@
142 EXPECT_TRUE(rect4.overlaps(rect3));
143 EXPECT_TRUE(rect3.overlaps(rect3));
144 }
145+
146+TEST(geometry, rectangle_intersection)
147+{
148+ using namespace testing;
149+ using namespace geom;
150+
151+ Rectangle const rect_base{{5,5}, {5,5}};
152+
153+ struct TestData
154+ {
155+ Rectangle const rect;
156+ Rectangle const intersection;
157+ };
158+
159+ std::vector<TestData> const test_data
160+ {
161+ { rect_base, rect_base },
162+ { Rectangle(), Rectangle() },
163+ { {{4,4}, {2,2}}, {{5,5}, {1,1}} },
164+ { {{5,4}, {5,2}}, {{5,5}, {5,1}} },
165+ { {{6,6}, {3,3}}, {{6,6}, {3,3}} },
166+ { {{9,9}, {1,1}}, {{9,9}, {1,1}} },
167+ { {{4,6}, {8,2}}, {{5,6}, {5,2}} }
168+ };
169+
170+ for (auto const& test_case : test_data)
171+ {
172+ EXPECT_THAT(rect_base.intersection_with(test_case.rect),
173+ Eq(test_case.intersection))
174+ << "test_case.rect = " << test_case.rect;
175+
176+ EXPECT_THAT(test_case.rect.intersection_with(rect_base),
177+ Eq(test_case.intersection))
178+ << "test_case.rect = " << test_case.rect;
179+ }
180+}

Subscribers

People subscribed via source and target branches