Mir

Merge lp:~alan-griffiths/mir/fix-1532202 into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 3274
Proposed branch: lp:~alan-griffiths/mir/fix-1532202
Merge into: lp:mir
Diff against target: 224 lines (+99/-9)
5 files modified
src/include/server/mir/scene/legacy_scene_change_notification.h (+8/-1)
src/server/compositor/multi_threaded_compositor.cpp (+26/-2)
src/server/compositor/multi_threaded_compositor.h (+2/-0)
src/server/scene/legacy_scene_change_notification.cpp (+62/-5)
tests/integration-tests/test_surface_stack_with_compositor.cpp (+1/-1)
To merge this branch: bzr merge lp:~alan-griffiths/mir/fix-1532202
Reviewer Review Type Date Requested Status
Gerry Boland (community) Approve
Kevin DuBois (community) Approve
Brandon Schaefer (community) Approve
Alexandros Frantzis (community) Approve
Daniel van Vugt Abstain
PS Jenkins bot (community) continuous-integration Approve
Mir CI Bot continuous-integration Approve
Review via email: mp+283190@code.launchpad.net

Commit message

compositor, scene: track which outputs are "damaged" by buffer posts

Description of the change

compositor, scene: track which outputs are "damaged" by buffer posts

This addresses the scenario in the linked bug, but there are still issues when using the AdorningDisplayBufferCompositor from the examples and opportunities to optimize the display updates in the (android) system compositor.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3251
https://mir-jenkins.ubuntu.com/job/mir-ci/87/
Executed test runs:
    None: https://mir-jenkins.ubuntu.com/job/generic-update-mp/87/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/87/rebuild

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3251
http://jenkins.qa.ubuntu.com/job/mir-ci/6059/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5590
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4497
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5546
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/300
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/383
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/383/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/383
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/383/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5543
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5543/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8002
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26789
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/296
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/296/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/152
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26801

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ci/6059/rebuild

review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Sounds like a handy optimization to have. Although I can't help but think we're missing the main issue. The main issue is probably related to the fact that you mentioned the system was mostly idle while we were failing to meet frame deadlines. So it's not necessarily a hard performance limit we hit as much as inefficient blocking/waiting somewhere.

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

> Sounds like a handy optimization to have. Although I can't help but think
> we're missing the main issue. The main issue is probably related to the fact
> that you mentioned the system was mostly idle while we were failing to meet
> frame deadlines. So it's not necessarily a hard performance limit we hit as
> much as inefficient blocking/waiting somewhere.

Yes, there's an iceberg of issues here. We should return to these and I've logged lp:1535894 to cover that.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Wasn't the issue Unity8? I recall QtMir is full of TODOs for multimonitor support, particularly around correct usage of compositor acquire IDs.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Aside from the above comment, my reason for not liking regional damage is based on previous experience in Compiz and even in mir_proving_server. Accurately tracking damage when you might be painting things using free-form OpenGL (not bound by any surface extents) like shadows is just too much of a pain to maintain. And on low-end systems can become a CPU bottleneck.

Put another way, given two monitors A and B, your window may only exist on A, but you really have to redraw both A and B in case shadows or some other side-effect creeps across.

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

Yes, QtMir and Unity8 also have work to do. But this issue was explicitly about Mir - and we ought to get this working as well as HWC allows.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

No tests?

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Another bigger concern is that this branch seems like a crutch. It lets us only just maintain a good frame rate so long as we only need to redraw one monitor. It is however an admission that we're not capable of redrawing multiple monitors per frame, which sounds like a problem that still needs fixing.

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

Not doing unnecessary rendering isn't "a crutch", especially on a battery powered device.

I don't consider our frame rate problems at an end, but I think this is an increment in the right direction.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It is a crutch if you've established the system is mostly idle and therefore we're not trying very hard to render sufficiently fast. We've had and still do have other such performance problems where it's a matter of real-time getting wasted in blocking system calls, but no CPU or GPU time getting wasted. Bug 1395421 comes to mind.

Adding a little complexity like this to improve performance seems harmless but is almost certainly missing the main issue.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

lgtm

Not 100% sure what:
run_cv.notify_one();

Is actually *running* but does it block on this thread? (Since we block at the top of that function).

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

> lgtm
>
> Not 100% sure what:
> run_cv.notify_one();
>
> Is actually *running* but does it block on this thread? (Since we block at the
> top of that function).

It is an implementation detail of compositor logic: the "run()" function blocks on run_cv awaiting a notification that there's work to do.

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

lgtm too, apart from having some MultiThreadedCompositor tests

review: Approve
Revision history for this message
Gerry Boland (gerboland) wrote :

Late test, but improves MM performance on N7

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/include/server/mir/scene/legacy_scene_change_notification.h'
2--- src/include/server/mir/scene/legacy_scene_change_notification.h 2015-02-22 07:46:25 +0000
3+++ src/include/server/mir/scene/legacy_scene_change_notification.h 2016-01-19 17:44:03 +0000
4@@ -27,6 +27,7 @@
5
6 namespace mir
7 {
8+namespace geometry { class Rectangle; }
9 namespace scene
10 {
11 class SurfaceObserver;
12@@ -40,6 +41,11 @@
13 LegacySceneChangeNotification(
14 std::function<void()> const& scene_notify_change,
15 std::function<void(int)> const& buffer_notify_change);
16+
17+ LegacySceneChangeNotification(
18+ std::function<void()> const& scene_notify_change,
19+ std::function<void(int frames, mir::geometry::Rectangle const& damage)> const& damage_notify_change);
20+
21 ~LegacySceneChangeNotification();
22
23 void surface_added(Surface* surface) override;
24@@ -54,7 +60,8 @@
25 private:
26 std::function<void()> const scene_notify_change;
27 std::function<void(int)> const buffer_notify_change;
28-
29+ std::function<void(int frames, mir::geometry::Rectangle const& damage)> const damage_notify_change;
30+
31 std::mutex surface_observers_guard;
32 std::map<Surface*, std::weak_ptr<SurfaceObserver>> surface_observers;
33
34
35=== modified file 'src/server/compositor/multi_threaded_compositor.cpp'
36--- src/server/compositor/multi_threaded_compositor.cpp 2015-12-14 15:38:23 +0000
37+++ src/server/compositor/multi_threaded_compositor.cpp 2016-01-19 17:44:03 +0000
38@@ -130,6 +130,7 @@
39 * to ensure all surfaces' queues are fully drained.
40 */
41 frames_scheduled--;
42+ not_posted_yet = false;
43 lock.unlock();
44
45 for (auto& tuple : compositors)
46@@ -198,6 +199,21 @@
47 }
48 }
49
50+ void schedule_compositing(int num_frames, geometry::Rectangle const& damage)
51+ {
52+ std::lock_guard<std::mutex> lock{run_mutex};
53+ bool took_damage = not_posted_yet;
54+
55+ group.for_each_display_buffer([&](mg::DisplayBuffer& buffer)
56+ { if (damage.overlaps(buffer.view_area())) took_damage = true; });
57+
58+ if (took_damage && num_frames > frames_scheduled)
59+ {
60+ frames_scheduled = num_frames;
61+ run_cv.notify_one();
62+ }
63+ }
64+
65 void stop()
66 {
67 std::lock_guard<std::mutex> lock{run_mutex};
68@@ -224,6 +240,7 @@
69 std::shared_ptr<CompositorReport> const report;
70 std::promise<void> started;
71 std::future<void> started_future;
72+ bool not_posted_yet = true;
73 };
74
75 }
76@@ -252,9 +269,9 @@
77 {
78 schedule_compositing(1);
79 },
80- [this](int num)
81+ [this](int num, geometry::Rectangle const& damage)
82 {
83- schedule_compositing(num);
84+ schedule_compositing(num, damage);
85 });
86 }
87
88@@ -270,6 +287,13 @@
89 f->schedule_compositing(num);
90 }
91
92+void mc::MultiThreadedCompositor::schedule_compositing(int num, geometry::Rectangle const& damage) const
93+{
94+ report->scheduled();
95+ for (auto& f : thread_functors)
96+ f->schedule_compositing(num, damage);
97+}
98+
99 void mc::MultiThreadedCompositor::start()
100 {
101 auto stopped = CompositorState::stopped;
102
103=== modified file 'src/server/compositor/multi_threaded_compositor.h'
104--- src/server/compositor/multi_threaded_compositor.h 2015-07-16 07:03:19 +0000
105+++ src/server/compositor/multi_threaded_compositor.h 2016-01-19 17:44:03 +0000
106@@ -31,6 +31,7 @@
107
108 namespace mir
109 {
110+namespace geometry { class Rectangle; }
111 namespace graphics
112 {
113 class Display;
114@@ -91,6 +92,7 @@
115 bool compose_on_start;
116
117 void schedule_compositing(int number_composites);
118+ void schedule_compositing(int number_composites, geometry::Rectangle const& damage) const;
119
120 std::shared_ptr<mir::scene::Observer> observer;
121 mir::thread::BasicThreadPool thread_pool;
122
123=== modified file 'src/server/scene/legacy_scene_change_notification.cpp'
124--- src/server/scene/legacy_scene_change_notification.cpp 2015-09-18 15:37:25 +0000
125+++ src/server/scene/legacy_scene_change_notification.cpp 2016-01-19 17:44:03 +0000
126@@ -34,11 +34,60 @@
127 {
128 }
129
130+ms::LegacySceneChangeNotification::LegacySceneChangeNotification(
131+ std::function<void()> const& scene_notify_change,
132+ std::function<void(int frames, mir::geometry::Rectangle const& damage)> const& damage_notify_change) :
133+ scene_notify_change(scene_notify_change),
134+ damage_notify_change(damage_notify_change)
135+{
136+}
137+
138 ms::LegacySceneChangeNotification::~LegacySceneChangeNotification()
139 {
140 end_observation();
141 }
142
143+namespace
144+{
145+class NonLegacySurfaceChangeNotification : public ms::LegacySurfaceChangeNotification
146+{
147+public:
148+ NonLegacySurfaceChangeNotification(
149+ std::function<void()> const& notify_scene_change,
150+ std::function<void(int frames, mir::geometry::Rectangle const& damage)> const& damage_notify_change,
151+ ms::Surface* surface);
152+
153+ void moved_to(mir::geometry::Point const& /*top_left*/) override;
154+ void frame_posted(int frames_available, mir::geometry::Size const& size) override;
155+
156+private:
157+ mir::geometry::Point top_left;
158+ std::function<void(int frames, mir::geometry::Rectangle const& damage)> const damage_notify_change;
159+};
160+
161+NonLegacySurfaceChangeNotification::NonLegacySurfaceChangeNotification(
162+ std::function<void()> const& notify_scene_change,
163+ std::function<void(int frames, mir::geometry::Rectangle const& damage)> const& damage_notify_change,
164+ ms::Surface* surface) :
165+ ms::LegacySurfaceChangeNotification(notify_scene_change, {}),
166+ damage_notify_change(damage_notify_change)
167+{
168+ top_left = surface->top_left();
169+}
170+
171+void NonLegacySurfaceChangeNotification::moved_to(mir::geometry::Point const& top_left)
172+{
173+ this->top_left = top_left;
174+ ms::LegacySurfaceChangeNotification::moved_to(top_left);
175+}
176+
177+void NonLegacySurfaceChangeNotification::frame_posted(int frames_available, mir::geometry::Size const& size)
178+{
179+ mir::geometry::Rectangle const update_region{top_left, size};
180+ damage_notify_change(frames_available, update_region);
181+}
182+}
183+
184 void ms::LegacySceneChangeNotification::add_surface_observer(ms::Surface* surface)
185 {
186 auto notifier = [surface, this, was_visible = false] () mutable
187@@ -48,11 +97,19 @@
188 was_visible = surface->visible();
189 };
190
191- auto observer = std::make_shared<ms::LegacySurfaceChangeNotification>(
192- notifier, buffer_notify_change);
193- surface->add_observer(observer);
194-
195- {
196+ if (buffer_notify_change)
197+ {
198+ auto observer = std::make_shared<LegacySurfaceChangeNotification>(notifier, buffer_notify_change);
199+ surface->add_observer(observer);
200+
201+ std::unique_lock<decltype(surface_observers_guard)> lg(surface_observers_guard);
202+ surface_observers[surface] = observer;
203+ }
204+ else
205+ {
206+ auto observer = std::make_shared<NonLegacySurfaceChangeNotification>(notifier, damage_notify_change, surface);
207+ surface->add_observer(observer);
208+
209 std::unique_lock<decltype(surface_observers_guard)> lg(surface_observers_guard);
210 surface_observers[surface] = observer;
211 }
212
213=== modified file 'tests/integration-tests/test_surface_stack_with_compositor.cpp'
214--- tests/integration-tests/test_surface_stack_with_compositor.cpp 2015-11-05 11:51:04 +0000
215+++ tests/integration-tests/test_surface_stack_with_compositor.cpp 2016-01-19 17:44:03 +0000
216@@ -144,7 +144,7 @@
217 std::shared_ptr<mtd::MockBufferBundle> mock_buffer_stream;
218 std::shared_ptr<ms::BasicSurface> stub_surface;
219 ms::SurfaceCreationParameters default_params;
220- mtd::StubBuffer stubbuf;
221+ mtd::StubBuffer stubbuf{geom::Size{1,1}};
222 CountingDisplaySyncGroup stub_primary_db;
223 CountingDisplaySyncGroup stub_secondary_db;
224 StubDisplay stub_display{stub_primary_db, stub_secondary_db};

Subscribers

People subscribed via source and target branches