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
=== modified file 'include/shared/mir/geometry/rectangle.h'
--- include/shared/mir/geometry/rectangle.h 2014-04-23 18:51:37 +0000
+++ include/shared/mir/geometry/rectangle.h 2014-07-10 09:06:31 +0000
@@ -32,6 +32,13 @@
3232
33struct Rectangle33struct Rectangle
34{34{
35 Rectangle() = default;
36
37 Rectangle(Point const& top_left, Size const& size)
38 : top_left{top_left}, size{size}
39 {
40 }
41
35 Point top_left;42 Point top_left;
36 Size size;43 Size size;
3744
@@ -55,6 +62,8 @@
55 bool contains(Rectangle const& r) const;62 bool contains(Rectangle const& r) const;
5663
57 bool overlaps(Rectangle const& r) const;64 bool overlaps(Rectangle const& r) const;
65
66 Rectangle intersection_with(Rectangle const& r) const;
58};67};
5968
60inline bool operator == (Rectangle const& lhs, Rectangle const& rhs)69inline bool operator == (Rectangle const& lhs, Rectangle const& rhs)
6170
=== modified file 'src/server/compositor/occlusion.cpp'
--- src/server/compositor/occlusion.cpp 2014-06-23 17:19:22 +0000
+++ src/server/compositor/occlusion.cpp 2014-07-10 09:06:31 +0000
@@ -34,7 +34,9 @@
34 Rectangle const& area,34 Rectangle const& area,
35 std::vector<Rectangle>& coverage)35 std::vector<Rectangle>& coverage)
36{36{
37 static const glm::mat4 identity;37 static glm::mat4 const identity;
38 static Rectangle const empty{};
39
38 if (renderable.transformation() != identity)40 if (renderable.transformation() != identity)
39 return false; // Weirdly transformed. Assume never occluded.41 return false; // Weirdly transformed. Assume never occluded.
4042
@@ -44,15 +46,16 @@
44 if (!renderable.visible())46 if (!renderable.visible())
45 return true; //invisible; definitely occluded.47 return true; //invisible; definitely occluded.
4648
47 // Not weirdly transformed but also not on this monitor? Don't care...49 auto const& window = renderable.screen_position();
48 if (!area.overlaps(renderable.screen_position()))50 auto const& clipped_window = window.intersection_with(area);
49 return true; // Not on the display; definitely occluded.51
52 if (clipped_window == empty)
53 return true; // Not in the area; definitely occluded.
5054
51 bool occluded = false;55 bool occluded = false;
52 Rectangle const& window = renderable.screen_position();56 for (auto const& r : coverage)
53 for (const auto &r : coverage)
54 {57 {
55 if (r.contains(window))58 if (r.contains(clipped_window))
56 {59 {
57 occluded = true;60 occluded = true;
58 break;61 break;
@@ -60,7 +63,7 @@
60 }63 }
6164
62 if (!occluded && renderable.alpha() == 1.0f && !renderable.shaped())65 if (!occluded && renderable.alpha() == 1.0f && !renderable.shaped())
63 coverage.push_back(window);66 coverage.push_back(clipped_window);
6467
65 return occluded;68 return occluded;
66}69}
6770
=== modified file 'src/shared/geometry/rectangle.cpp'
--- src/shared/geometry/rectangle.cpp 2014-04-21 17:18:14 +0000
+++ src/shared/geometry/rectangle.cpp 2014-07-10 09:06:31 +0000
@@ -18,7 +18,7 @@
1818
19#include "mir/geometry/rectangle.h"19#include "mir/geometry/rectangle.h"
2020
21#include <cassert>21#include <algorithm>
2222
23namespace geom = mir::geometry;23namespace geom = mir::geometry;
2424
@@ -76,3 +76,16 @@
76 return false;76 return false;
77 }77 }
78}78}
79
80geom::Rectangle geom::Rectangle::intersection_with(Rectangle const& r) const
81{
82 int const a = std::max(top_left.x.as_int(), r.top_left.x.as_int());
83 int const b = std::min(bottom_right().x.as_int(), r.bottom_right().x.as_int());
84 int const c = std::max(top_left.y.as_int(), r.top_left.y.as_int());
85 int const d = std::min(bottom_right().y.as_int(), r.bottom_right().y.as_int());
86
87 if (a < b && c < d)
88 return {{a, c}, {b - a, d - c}};
89 else
90 return geom::Rectangle();
91}
7992
=== modified file 'tests/unit-tests/compositor/test_occlusion.cpp'
--- tests/unit-tests/compositor/test_occlusion.cpp 2014-06-24 14:02:25 +0000
+++ tests/unit-tests/compositor/test_occlusion.cpp 2014-07-10 09:06:31 +0000
@@ -209,3 +209,19 @@
209 EXPECT_THAT(renderables_from(occlusions), ElementsAre(window3, window2, window1));209 EXPECT_THAT(renderables_from(occlusions), ElementsAre(window3, window2, window1));
210 EXPECT_THAT(renderables_from(elements), ElementsAre(window5, window4, window0));210 EXPECT_THAT(renderables_from(elements), ElementsAre(window5, window4, window0));
211}211}
212
213TEST_F(OcclusionFilterTest,
214 occludes_partially_onscreen_window_when_onscreen_part_is_covered_by_another_window)
215{
216 auto const partially_onscreen = std::make_shared<mtd::FakeRenderable>(-50, 100, 150, 100);
217 auto const covering = std::make_shared<mtd::FakeRenderable>(0, 100, 100, 100);
218 auto elements = scene_elements_from({
219 partially_onscreen,
220 covering
221 });
222
223 auto const& occlusions = filter_occlusions_from(elements, monitor_rect);
224
225 EXPECT_THAT(renderables_from(occlusions), ElementsAre(partially_onscreen));
226 EXPECT_THAT(renderables_from(elements), ElementsAre(covering));
227}
212228
=== modified file 'tests/unit-tests/geometry/test-rectangle.cpp'
--- tests/unit-tests/geometry/test-rectangle.cpp 2013-10-15 08:53:10 +0000
+++ tests/unit-tests/geometry/test-rectangle.cpp 2014-07-10 09:06:31 +0000
@@ -21,6 +21,8 @@
21#include <gmock/gmock.h>21#include <gmock/gmock.h>
22#include <gtest/gtest.h>22#include <gtest/gtest.h>
2323
24#include <vector>
25
24namespace geom = mir::geometry;26namespace geom = mir::geometry;
2527
26TEST(geometry, rectangle)28TEST(geometry, rectangle)
@@ -195,3 +197,39 @@
195 EXPECT_TRUE(rect4.overlaps(rect3));197 EXPECT_TRUE(rect4.overlaps(rect3));
196 EXPECT_TRUE(rect3.overlaps(rect3));198 EXPECT_TRUE(rect3.overlaps(rect3));
197}199}
200
201TEST(geometry, rectangle_intersection)
202{
203 using namespace testing;
204 using namespace geom;
205
206 Rectangle const rect_base{{5,5}, {5,5}};
207
208 struct TestData
209 {
210 Rectangle const rect;
211 Rectangle const intersection;
212 };
213
214 std::vector<TestData> const test_data
215 {
216 { rect_base, rect_base },
217 { Rectangle(), Rectangle() },
218 { {{4,4}, {2,2}}, {{5,5}, {1,1}} },
219 { {{5,4}, {5,2}}, {{5,5}, {5,1}} },
220 { {{6,6}, {3,3}}, {{6,6}, {3,3}} },
221 { {{9,9}, {1,1}}, {{9,9}, {1,1}} },
222 { {{4,6}, {8,2}}, {{5,6}, {5,2}} }
223 };
224
225 for (auto const& test_case : test_data)
226 {
227 EXPECT_THAT(rect_base.intersection_with(test_case.rect),
228 Eq(test_case.intersection))
229 << "test_case.rect = " << test_case.rect;
230
231 EXPECT_THAT(test_case.rect.intersection_with(rect_base),
232 Eq(test_case.intersection))
233 << "test_case.rect = " << test_case.rect;
234 }
235}

Subscribers

People subscribed via source and target branches