Merge lp:~alan-griffiths/mir/fix-1535894-alt into lp:mir
- fix-1535894-alt
- Merge into development-branch
Status: | Rejected |
---|---|
Rejected by: | Alan Griffiths |
Proposed branch: | lp:~alan-griffiths/mir/fix-1535894-alt |
Merge into: | lp:mir |
Diff against target: |
984 lines (+181/-263) 26 files modified
examples/render_surfaces.cpp (+3/-2) examples/server_example_adorning_compositor.cpp (+12/-1) examples/server_example_adorning_compositor.h (+1/-1) include/server/mir/compositor/display_buffer_compositor.h (+1/-1) include/server/mir/compositor/scene.h (+0/-10) include/server/mir/compositor/scene_element.h (+1/-0) include/test/mir/test/doubles/null_display_buffer_compositor_factory.h (+2/-1) playground/demo-shell/demo_compositor.cpp (+13/-1) playground/demo-shell/demo_compositor.h (+1/-1) src/server/compositor/default_display_buffer_compositor.cpp (+43/-46) src/server/compositor/default_display_buffer_compositor.h (+1/-1) src/server/compositor/multi_threaded_compositor.cpp (+3/-11) src/server/scene/rendering_tracker.cpp (+9/-0) src/server/scene/rendering_tracker.h (+1/-0) src/server/scene/surface_stack.cpp (+10/-24) src/server/scene/surface_stack.h (+0/-1) tests/acceptance-tests/test_buffer_stream_arrangement.cpp (+2/-2) tests/acceptance-tests/test_client_scaling.cpp (+2/-1) tests/acceptance-tests/test_render_override.cpp (+3/-1) tests/include/mir/test/doubles/stub_scene.h (+0/-4) tests/include/mir/test/doubles/stub_scene_element.h (+5/-0) tests/integration-tests/test_server_shutdown.cpp (+1/-1) tests/unit-tests/compositor/test_compositing_screencast.cpp (+4/-3) tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp (+44/-10) tests/unit-tests/compositor/test_multi_threaded_compositor.cpp (+19/-22) tests/unit-tests/scene/test_surface_stack.cpp (+0/-118) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/fix-1535894-alt |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Mir CI Bot | continuous-integration | Approve | |
Daniel van Vugt | Needs Fixing | ||
Review via email: mp+285223@code.launchpad.net |
Commit message
compositor, scene: Use the DisplayBufferCo
Description of the change
compositor, scene: Use the DisplayBufferCo
This doesn't include logic that allows -c 3274 to be reverted, but if this approach is favoured, then I'll rework that to put the DisplayBufferCo
Mir CI Bot (mir-ci-bot) wrote : | # |
Alan Griffiths (alan-griffiths) wrote : | # |
Errors look unrelated:
15:52:50 Setting up libuuid1:amd64 (2.27.1-1ubuntu4) ...
15:52:50 dpkg: error processing package libuuid1:amd64 (--configure):
15:52:50 subprocess installed post-installation script returned error exit status 1
15:52:50 Processing triggers for libc-bin (2.21-0ubuntu5) ...
15:52:51 Errors were encountered while processing:
15:52:51 libuuid1:amd64
15:52:51 W: No sandbox user '_apt' on the system, can not drop privileges
15:52:51 E: Sub-process /usr/bin/dpkg returned an error code (1)
15:52:51 apt-get failed.
15:52:51 Package installation failed
15:52:55 dpkg: error processing package libuuid1:i386 (--configure):
15:52:55 subprocess installed post-installation script returned error exit status 1
15:52:55 Processing triggers for libc-bin (2.21-0ubuntu5) ...
15:52:55 Errors were encountered while processing:
15:52:55 libuuid1:i386
15:52:55 W: No sandbox user '_apt' on the system, can not drop privileges
15:52:55 E: Sub-process /usr/bin/dpkg returned an error code (1)
15:52:55 apt-get failed.
15:52:55 Package installation failed
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3300
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3300
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3300
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
1. Needs info: I thought the goal here was to skip rendering on idle displays. That code doesn't seem to be present yet, so maybe it comes later? It would be: composite() returns "I had nothing new to render" so then post() never gets called. You either need to composite and post, or do neither. But never composite without post (wasted of GPU), and never post without composite (uninitialized pixels appear on screen).
Although that raises an important question: Is the bug safe to fix at all under the new display groups architecture? How do we safely tell Android to only post one of the displays in the group but not the other? I'm wondering if it's even possible to fix this under the display group approach... because you must either have one composite and one post, or zero of all.
2. Needs fixing: Please add the FIXME comment back in. It's an important one we shouldn't forget.
I'm also nervous that we're rewriting so much code that covers years of regression fixes. But that's not quite a blocking issue.
Daniel van Vugt (vanvugt) wrote : | # |
3. This looks like important code that will cause regressions if removed:
- int result = scene_changed ? 1 : 0;
That tells us to redraw the screen if a window has been dragged, but no windows contents changed. Obviously was missing a test.
Daniel van Vugt (vanvugt) wrote : | # |
OK, assuming Android has some magic workaround built-in to cope with posting a display group where only half of that group has been rendered, what we actually want instead of this branch is:
bool composited = false
for each compositor:
composited |= compositor-
if (composited)
group.post();
That also means you can keep the frame counting logic where it is in the scene. No need to duplicate it into each compositor implementation.
But if Android can't handle half the monitors being rendered and then being told to post the whole group, then we actually can't safely do any of this at all...
Alan Griffiths (alan-griffiths) wrote : | # |
> 1. Needs info: I thought the goal here was to skip rendering on idle displays.
> That code doesn't seem to be present yet, so maybe it comes later? It would
> be: composite() returns "I had nothing new to render" so then post() never
> gets called. You either need to composite and post, or do neither. But never
> composite without post (wasted of GPU), and never post without composite
> (uninitialized pixels appear on screen).
Nope.
The point of *this* MP is that the DisplayBufferCo
With the logic in scene we were counting buffers belonging to surfaces that had not contributed to rendering. (And would not be consumed by the consequent render pass.)
In the scenario from the linked bug the nested server would repeatedly schedule a recomposite of whichever display on which nothing had been posted.
> 2. Needs fixing: Please add the FIXME comment back in. It's an important one
> we shouldn't forget.
OK
Alan Griffiths (alan-griffiths) wrote : | # |
> 3. This looks like important code that will cause regressions if removed:
> - int result = scene_changed ? 1 : 0;
>
> That tells us to redraw the screen if a window has been dragged, but no
> windows contents changed. Obviously was missing a test.
Obviously, this code duplicated the effect of CompositingFunc
Daniel van Vugt (vanvugt) wrote : | # |
Oh cool. That all sounds like good news then. I'll need to re-evaluate later.
Daniel van Vugt (vanvugt) wrote : | # |
(1) Thanks for explaining. So I took some time today adding and analysing some debug logging to try and catch Mir in the act of repeatedly scheduling frames on some display but never consuming them. Unfortunately I can't yet reproduce such a busy wait but that could be just that I'm using desktop, or it could just be bad luck. So I'm assuming there's still a theoretical problem needing fixing.
But now I'm curious: You've clarified you're just fixing a busy wait. Or as I would say it "made Mir sleep properly". That's very good for power management, but only a small piece of the performance story. Even if this branch is working perfectly, you're still re-posting all displays on every frame (including the idle one) while any one of them is animating. So this is really a power management fix, but how is it an improvement to performance? You haven't changed the rendering load, and haven't reduced the number of posts either.
(2) Needs fixing: FIXME comment is still missing.
(4) I'm not yet confident this branch is working. As stated in (1) I can't yet put together a manual test case on desktop to reproduce any issue, and the diff below shows no new regression tests for anything getting fixed. So I think you need to try and write a regression test for the issue.
(5) In theory there's a much simpler solution you should consider. That is just make every call to BasicSurface:
Daniel van Vugt (vanvugt) wrote : | # |
(1) "You haven't changed the rendering load, and haven't reduced the number of posts either" [while any display is changing anyway]
(5) Here's possible alternative solution:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
> but only a small piece of the performance story. Even if this branch is
> working perfectly, you're still re-posting all displays on every frame
> (including the idle one) while any one of them is animating.
Remember, this is in the nested server which has a CompositingFunctor for each output.
The earlier change (that you have valid concerns about) ensures that the CompositingFunctor doesn't run for changes that do not apply to its display buffers compositor.
> So this is really
> a power management fix, but how is it an improvement to performance? You
> haven't changed the rendering load, and haven't reduced the number of posts
> either.
The problem this addresses occurs whenever the "idle" CompositingFunctor runs. First it composites the surfaces visible to its DBC and then checks the scene for unconsumed frames. Updates on the other screen cause it to increment frames_scheduled and composite unnecessarily.
By only checking for unconsumed frames in the surfaces that have been rendered we avoid that extra pass.
> (2) Needs fixing: FIXME comment is still missing.
>
> (4) I'm not yet confident this branch is working. As stated in (1) I can't yet
> put together a manual test case on desktop to reproduce any issue, and the
> diff below shows no new regression tests for anything getting fixed. So I
> think you need to try and write a regression test for the issue.
Ack.
- 3301. By Alan Griffiths
-
merge lp:mir
- 3302. By Alan Griffiths
-
Reinstate FIXME comment
- 3303. By Alan Griffiths
-
Remove some unused headers
Alan Griffiths (alan-griffiths) wrote : | # |
nm. -c 3301 seems to have addressed the problem I was seeing. (Not sure how, so I must have misinterpreted the system behaviour - we need better reporting out of the compositor.)
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:3303
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:3303
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
- 3303. By Alan Griffiths
-
Remove some unused headers
- 3302. By Alan Griffiths
-
Reinstate FIXME comment
- 3301. By Alan Griffiths
-
merge lp:mir
- 3300. By Alan Griffiths
-
Cleaner code in examples
- 3299. By Alan Griffiths
-
Cleaner code (that also passes StaleFrames.* tests)
- 3298. By Alan Griffiths
-
Add corresponding DefaultDisplayB
ufferCompositor tests - 3297. By Alan Griffiths
-
Remove unnecessary Scene::
frames_ pending( ) - 3296. By Alan Griffiths
-
Fixup broken test
- 3295. By Alan Griffiths
-
First pass at pending buffer count
Preview Diff
1 | === modified file 'examples/render_surfaces.cpp' | |||
2 | --- examples/render_surfaces.cpp 2016-01-29 08:18:22 +0000 | |||
3 | +++ examples/render_surfaces.cpp 2016-02-11 14:50:57 +0000 | |||
4 | @@ -241,7 +241,7 @@ | |||
5 | 241 | { | 241 | { |
6 | 242 | } | 242 | } |
7 | 243 | 243 | ||
9 | 244 | void composite(mc::SceneElementSequence&& scene_sequence) override | 244 | int composite(mc::SceneElementSequence&& scene_sequence) override |
10 | 245 | { | 245 | { |
11 | 246 | while (!created) std::this_thread::yield(); | 246 | while (!created) std::this_thread::yield(); |
12 | 247 | stop_watch.stop(); | 247 | stop_watch.stop(); |
13 | @@ -252,12 +252,13 @@ | |||
14 | 252 | stop_watch.restart(); | 252 | stop_watch.restart(); |
15 | 253 | } | 253 | } |
16 | 254 | 254 | ||
18 | 255 | db_compositor->composite(std::move(scene_sequence)); | 255 | auto const result = db_compositor->composite(std::move(scene_sequence)); |
19 | 256 | 256 | ||
20 | 257 | for (auto& m : moveables) | 257 | for (auto& m : moveables) |
21 | 258 | m.step(); | 258 | m.step(); |
22 | 259 | 259 | ||
23 | 260 | frames++; | 260 | frames++; |
24 | 261 | return result; | ||
25 | 261 | } | 262 | } |
26 | 262 | 263 | ||
27 | 263 | private: | 264 | private: |
28 | 264 | 265 | ||
29 | === modified file 'examples/server_example_adorning_compositor.cpp' | |||
30 | --- examples/server_example_adorning_compositor.cpp 2016-02-08 17:58:09 +0000 | |||
31 | +++ examples/server_example_adorning_compositor.cpp 2016-02-11 14:50:57 +0000 | |||
32 | @@ -174,7 +174,7 @@ | |||
33 | 174 | } | 174 | } |
34 | 175 | } | 175 | } |
35 | 176 | 176 | ||
37 | 177 | void me::AdorningDisplayBufferCompositor::composite(compositor::SceneElementSequence&& scene_sequence) | 177 | int me::AdorningDisplayBufferCompositor::composite(compositor::SceneElementSequence&& scene_sequence) |
38 | 178 | { | 178 | { |
39 | 179 | report->began_frame(this); | 179 | report->began_frame(this); |
40 | 180 | 180 | ||
41 | @@ -250,4 +250,15 @@ | |||
42 | 250 | render_target->swap_buffers(); | 250 | render_target->swap_buffers(); |
43 | 251 | 251 | ||
44 | 252 | report->finished_frame(this); | 252 | report->finished_frame(this); |
45 | 253 | |||
46 | 254 | auto max_pending_buffers = 0; | ||
47 | 255 | for (auto const& element : scene_sequence) | ||
48 | 256 | { | ||
49 | 257 | auto buffers_for_element = element->pending_buffers(); | ||
50 | 258 | |||
51 | 259 | if (max_pending_buffers < buffers_for_element) | ||
52 | 260 | max_pending_buffers = buffers_for_element; | ||
53 | 261 | } | ||
54 | 262 | |||
55 | 263 | return max_pending_buffers; | ||
56 | 253 | } | 264 | } |
57 | 254 | 265 | ||
58 | === modified file 'examples/server_example_adorning_compositor.h' | |||
59 | --- examples/server_example_adorning_compositor.h 2016-01-29 08:18:22 +0000 | |||
60 | +++ examples/server_example_adorning_compositor.h 2016-02-11 14:50:57 +0000 | |||
61 | @@ -40,7 +40,7 @@ | |||
62 | 40 | graphics::DisplayBuffer&, std::tuple<float, float, float> const& background_rgb, | 40 | graphics::DisplayBuffer&, std::tuple<float, float, float> const& background_rgb, |
63 | 41 | std::shared_ptr<compositor::CompositorReport> const& report); | 41 | std::shared_ptr<compositor::CompositorReport> const& report); |
64 | 42 | 42 | ||
66 | 43 | void composite(compositor::SceneElementSequence&& scene_sequence) override; | 43 | int composite(compositor::SceneElementSequence&& scene_sequence) override; |
67 | 44 | private: | 44 | private: |
68 | 45 | graphics::DisplayBuffer& db; | 45 | graphics::DisplayBuffer& db; |
69 | 46 | renderer::gl::RenderTarget* const render_target; | 46 | renderer::gl::RenderTarget* const render_target; |
70 | 47 | 47 | ||
71 | === modified file 'include/server/mir/compositor/display_buffer_compositor.h' | |||
72 | --- include/server/mir/compositor/display_buffer_compositor.h 2015-02-22 07:46:25 +0000 | |||
73 | +++ include/server/mir/compositor/display_buffer_compositor.h 2016-02-11 14:50:57 +0000 | |||
74 | @@ -32,7 +32,7 @@ | |||
75 | 32 | public: | 32 | public: |
76 | 33 | virtual ~DisplayBufferCompositor() = default; | 33 | virtual ~DisplayBufferCompositor() = default; |
77 | 34 | 34 | ||
79 | 35 | virtual void composite(SceneElementSequence&& scene_sequence) = 0; | 35 | virtual int composite(SceneElementSequence&& scene_sequence) = 0; |
80 | 36 | 36 | ||
81 | 37 | protected: | 37 | protected: |
82 | 38 | DisplayBufferCompositor() = default; | 38 | DisplayBufferCompositor() = default; |
83 | 39 | 39 | ||
84 | === modified file 'include/server/mir/compositor/scene.h' | |||
85 | --- include/server/mir/compositor/scene.h 2015-02-22 07:46:25 +0000 | |||
86 | +++ include/server/mir/compositor/scene.h 2016-02-11 14:50:57 +0000 | |||
87 | @@ -55,16 +55,6 @@ | |||
88 | 55 | */ | 55 | */ |
89 | 56 | virtual SceneElementSequence scene_elements_for(CompositorID id) = 0; | 56 | virtual SceneElementSequence scene_elements_for(CompositorID id) = 0; |
90 | 57 | 57 | ||
91 | 58 | /** | ||
92 | 59 | * Return the number of additional frames that you need to render to get | ||
93 | 60 | * fully up to date with the latest data in the scene. For a generic | ||
94 | 61 | * "scene change" this will be just 1. For surfaces that have multiple | ||
95 | 62 | * frames queued up however, it could be greater than 1. When the result | ||
96 | 63 | * reaches zero, you know you have consumed all the latest data from the | ||
97 | 64 | * scene. | ||
98 | 65 | */ | ||
99 | 66 | virtual int frames_pending(CompositorID id) const = 0; | ||
100 | 67 | |||
101 | 68 | virtual void register_compositor(CompositorID id) = 0; | 58 | virtual void register_compositor(CompositorID id) = 0; |
102 | 69 | virtual void unregister_compositor(CompositorID id) = 0; | 59 | virtual void unregister_compositor(CompositorID id) = 0; |
103 | 70 | 60 | ||
104 | 71 | 61 | ||
105 | === modified file 'include/server/mir/compositor/scene_element.h' | |||
106 | --- include/server/mir/compositor/scene_element.h 2015-06-17 05:20:42 +0000 | |||
107 | +++ include/server/mir/compositor/scene_element.h 2016-02-11 14:50:57 +0000 | |||
108 | @@ -38,6 +38,7 @@ | |||
109 | 38 | virtual std::shared_ptr<graphics::Renderable> renderable() const = 0; | 38 | virtual std::shared_ptr<graphics::Renderable> renderable() const = 0; |
110 | 39 | virtual void rendered() = 0; | 39 | virtual void rendered() = 0; |
111 | 40 | virtual void occluded() = 0; | 40 | virtual void occluded() = 0; |
112 | 41 | virtual int pending_buffers() const = 0; | ||
113 | 41 | 42 | ||
114 | 42 | //TODO: Decoration is opaque on purpose. It is only used by an internal example, | 43 | //TODO: Decoration is opaque on purpose. It is only used by an internal example, |
115 | 43 | // and this function should be removed from the public API. | 44 | // and this function should be removed from the public API. |
116 | 44 | 45 | ||
117 | === modified file 'include/test/mir/test/doubles/null_display_buffer_compositor_factory.h' | |||
118 | --- include/test/mir/test/doubles/null_display_buffer_compositor_factory.h 2016-01-29 08:18:22 +0000 | |||
119 | +++ include/test/mir/test/doubles/null_display_buffer_compositor_factory.h 2016-02-11 14:50:57 +0000 | |||
120 | @@ -39,11 +39,12 @@ | |||
121 | 39 | { | 39 | { |
122 | 40 | struct NullDisplayBufferCompositor : compositor::DisplayBufferCompositor | 40 | struct NullDisplayBufferCompositor : compositor::DisplayBufferCompositor |
123 | 41 | { | 41 | { |
125 | 42 | void composite(compositor::SceneElementSequence&&) | 42 | int composite(compositor::SceneElementSequence&&) |
126 | 43 | { | 43 | { |
127 | 44 | // yield() is needed to ensure reasonable runtime under | 44 | // yield() is needed to ensure reasonable runtime under |
128 | 45 | // valgrind for some tests | 45 | // valgrind for some tests |
129 | 46 | std::this_thread::yield(); | 46 | std::this_thread::yield(); |
130 | 47 | return 0; | ||
131 | 47 | } | 48 | } |
132 | 48 | }; | 49 | }; |
133 | 49 | 50 | ||
134 | 50 | 51 | ||
135 | === modified file 'playground/demo-shell/demo_compositor.cpp' | |||
136 | --- playground/demo-shell/demo_compositor.cpp 2016-01-29 08:18:22 +0000 | |||
137 | +++ playground/demo-shell/demo_compositor.cpp 2016-02-11 14:50:57 +0000 | |||
138 | @@ -58,7 +58,7 @@ | |||
139 | 58 | f(*i); | 58 | f(*i); |
140 | 59 | } | 59 | } |
141 | 60 | 60 | ||
143 | 61 | void me::DemoCompositor::composite(mc::SceneElementSequence&& elements) | 61 | int me::DemoCompositor::composite(mc::SceneElementSequence&& elements) |
144 | 62 | { | 62 | { |
145 | 63 | report->began_frame(this); | 63 | report->began_frame(this); |
146 | 64 | //a simple filtering out of renderables that shouldn't be drawn | 64 | //a simple filtering out of renderables that shouldn't be drawn |
147 | @@ -106,6 +106,16 @@ | |||
148 | 106 | nonrenderlist_elements |= embellished; | 106 | nonrenderlist_elements |= embellished; |
149 | 107 | } | 107 | } |
150 | 108 | 108 | ||
151 | 109 | auto max_pending_buffers = 0; | ||
152 | 110 | for (auto const& element : elements) | ||
153 | 111 | { | ||
154 | 112 | // We're about to render a buffer, so don't count that one | ||
155 | 113 | auto buffers_for_element = element->pending_buffers() - 1; | ||
156 | 114 | |||
157 | 115 | if (max_pending_buffers < buffers_for_element) | ||
158 | 116 | max_pending_buffers = buffers_for_element; | ||
159 | 117 | } | ||
160 | 118 | |||
161 | 109 | /* | 119 | /* |
162 | 110 | * Note: Buffer lifetimes are ensured by the two objects holding | 120 | * Note: Buffer lifetimes are ensured by the two objects holding |
163 | 111 | * references to them; elements and renderable_list. | 121 | * references to them; elements and renderable_list. |
164 | @@ -141,6 +151,8 @@ | |||
165 | 141 | } | 151 | } |
166 | 142 | 152 | ||
167 | 143 | report->finished_frame(this); | 153 | report->finished_frame(this); |
168 | 154 | |||
169 | 155 | return max_pending_buffers; | ||
170 | 144 | } | 156 | } |
171 | 145 | 157 | ||
172 | 146 | void me::DemoCompositor::on_cursor_movement( | 158 | void me::DemoCompositor::on_cursor_movement( |
173 | 147 | 159 | ||
174 | === modified file 'playground/demo-shell/demo_compositor.h' | |||
175 | --- playground/demo-shell/demo_compositor.h 2015-02-22 07:46:25 +0000 | |||
176 | +++ playground/demo-shell/demo_compositor.h 2016-02-11 14:50:57 +0000 | |||
177 | @@ -50,7 +50,7 @@ | |||
178 | 50 | std::shared_ptr<compositor::CompositorReport> const& report); | 50 | std::shared_ptr<compositor::CompositorReport> const& report); |
179 | 51 | ~DemoCompositor(); | 51 | ~DemoCompositor(); |
180 | 52 | 52 | ||
182 | 53 | void composite(compositor::SceneElementSequence&& elements) override; | 53 | int composite(compositor::SceneElementSequence&& elements) override; |
183 | 54 | 54 | ||
184 | 55 | void zoom(float mag); | 55 | void zoom(float mag); |
185 | 56 | void on_cursor_movement(geometry::Point const& p); | 56 | void on_cursor_movement(geometry::Point const& p); |
186 | 57 | 57 | ||
187 | === modified file 'src/server/compositor/default_display_buffer_compositor.cpp' | |||
188 | --- src/server/compositor/default_display_buffer_compositor.cpp 2016-01-29 08:18:22 +0000 | |||
189 | +++ src/server/compositor/default_display_buffer_compositor.cpp 2016-02-11 14:50:57 +0000 | |||
190 | @@ -1,5 +1,5 @@ | |||
191 | 1 | /* | 1 | /* |
193 | 2 | * Copyright © 2012 Canonical Ltd. | 2 | * Copyright © 2012-2016 Canonical Ltd. |
194 | 3 | * | 3 | * |
195 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
196 | 5 | * under the terms of the GNU General Public License version 3, | 5 | * under the terms of the GNU General Public License version 3, |
197 | @@ -19,16 +19,13 @@ | |||
198 | 19 | 19 | ||
199 | 20 | #include "default_display_buffer_compositor.h" | 20 | #include "default_display_buffer_compositor.h" |
200 | 21 | 21 | ||
201 | 22 | #include "mir/compositor/scene.h" | ||
202 | 23 | #include "mir/compositor/scene_element.h" | 22 | #include "mir/compositor/scene_element.h" |
203 | 24 | #include "mir/compositor/renderer.h" | 23 | #include "mir/compositor/renderer.h" |
204 | 25 | #include "mir/graphics/renderable.h" | 24 | #include "mir/graphics/renderable.h" |
205 | 26 | #include "mir/graphics/display_buffer.h" | 25 | #include "mir/graphics/display_buffer.h" |
206 | 27 | #include "mir/graphics/buffer.h" | 26 | #include "mir/graphics/buffer.h" |
207 | 28 | #include "mir/compositor/buffer_stream.h" | ||
208 | 29 | #include "occlusion.h" | 27 | #include "occlusion.h" |
211 | 30 | #include <mutex> | 28 | |
210 | 31 | #include <cstdlib> | ||
212 | 32 | #include <algorithm> | 29 | #include <algorithm> |
213 | 33 | 30 | ||
214 | 34 | namespace mc = mir::compositor; | 31 | namespace mc = mir::compositor; |
215 | @@ -44,52 +41,52 @@ | |||
216 | 44 | { | 41 | { |
217 | 45 | } | 42 | } |
218 | 46 | 43 | ||
220 | 47 | void mc::DefaultDisplayBufferCompositor::composite(mc::SceneElementSequence&& scene_elements) | 44 | int mc::DefaultDisplayBufferCompositor::composite(SceneElementSequence&& scene_elements) |
221 | 48 | { | 45 | { |
222 | 49 | report->began_frame(this); | 46 | report->began_frame(this); |
223 | 50 | 47 | ||
228 | 51 | auto const& view_area = display_buffer.view_area(); | 48 | for (auto const& element : filter_occlusions_from(scene_elements, display_buffer.view_area())) |
225 | 52 | auto const& occlusions = mc::filter_occlusions_from(scene_elements, view_area); | ||
226 | 53 | |||
227 | 54 | for (auto const& element : occlusions) | ||
229 | 55 | element->occluded(); | 49 | element->occluded(); |
230 | 56 | 50 | ||
233 | 57 | mg::RenderableList renderable_list; | 51 | { |
234 | 58 | renderable_list.reserve(scene_elements.size()); | 52 | mg::RenderableList renderable_list; |
235 | 53 | renderable_list.reserve(scene_elements.size()); | ||
236 | 54 | |||
237 | 55 | transform(begin(scene_elements), end(scene_elements), back_inserter(renderable_list), [] (auto& element) | ||
238 | 56 | { | ||
239 | 57 | element->rendered(); | ||
240 | 58 | return element->renderable(); | ||
241 | 59 | }); | ||
242 | 60 | |||
243 | 61 | if (display_buffer.post_renderables_if_optimizable(renderable_list)) | ||
244 | 62 | { | ||
245 | 63 | report->renderables_in_frame(this, renderable_list); | ||
246 | 64 | renderer->suspend(); | ||
247 | 65 | } | ||
248 | 66 | else | ||
249 | 67 | { | ||
250 | 68 | renderer->set_rotation(display_buffer.orientation()); | ||
251 | 69 | renderer->render(renderable_list); | ||
252 | 70 | |||
253 | 71 | report->renderables_in_frame(this, renderable_list); | ||
254 | 72 | report->rendered_frame(this); | ||
255 | 73 | } | ||
256 | 74 | } | ||
257 | 75 | |||
258 | 76 | report->finished_frame(this); | ||
259 | 77 | |||
260 | 78 | auto max_pending_buffers = 0; | ||
261 | 59 | for (auto const& element : scene_elements) | 79 | for (auto const& element : scene_elements) |
262 | 60 | { | 80 | { |
297 | 61 | element->rendered(); | 81 | auto buffers_for_element = element->pending_buffers(); |
298 | 62 | renderable_list.push_back(element->renderable()); | 82 | |
299 | 63 | } | 83 | if (max_pending_buffers < buffers_for_element) |
300 | 64 | 84 | max_pending_buffers = buffers_for_element; | |
301 | 65 | /* | 85 | } |
302 | 66 | * Note: Buffer lifetimes are ensured by the two objects holding | 86 | |
303 | 67 | * references to them; scene_elements and renderable_list. | 87 | return max_pending_buffers; |
304 | 68 | * So no buffer is going to be released back to the client till | 88 | |
305 | 69 | * both of those containers get destroyed (end of the function). | 89 | // Returning destroys the local renderable_list and the temporary scene_elements which releases |
306 | 70 | * Actually, there's a third reference held by the texture cache | 90 | // the buffers we did use back to the clients, before starting on the potentially slow flip(). |
307 | 71 | * in GLRenderer, but that gets released earlier in render(). | 91 | // FIXME: releasing the buffers is blocking a little because we drive IPC here (LP: #1395421) |
274 | 72 | */ | ||
275 | 73 | scene_elements.clear(); // Those in use are still in renderable_list | ||
276 | 74 | |||
277 | 75 | if (display_buffer.post_renderables_if_optimizable(renderable_list)) | ||
278 | 76 | { | ||
279 | 77 | report->renderables_in_frame(this, renderable_list); | ||
280 | 78 | renderer->suspend(); | ||
281 | 79 | } | ||
282 | 80 | else | ||
283 | 81 | { | ||
284 | 82 | renderer->set_rotation(display_buffer.orientation()); | ||
285 | 83 | renderer->render(renderable_list); | ||
286 | 84 | |||
287 | 85 | report->renderables_in_frame(this, renderable_list); | ||
288 | 86 | report->rendered_frame(this); | ||
289 | 87 | |||
290 | 88 | // Release the buffers we did use back to the clients, before starting | ||
291 | 89 | // on the potentially slow flip(). | ||
292 | 90 | // FIXME: This clear() call is blocking a little because we drive IPC here (LP: #1395421) | ||
293 | 91 | renderable_list.clear(); | ||
294 | 92 | } | ||
295 | 93 | |||
296 | 94 | report->finished_frame(this); | ||
308 | 95 | } | 92 | } |
309 | 96 | 93 | ||
310 | === modified file 'src/server/compositor/default_display_buffer_compositor.h' | |||
311 | --- src/server/compositor/default_display_buffer_compositor.h 2015-04-28 07:54:10 +0000 | |||
312 | +++ src/server/compositor/default_display_buffer_compositor.h 2016-02-11 14:50:57 +0000 | |||
313 | @@ -43,7 +43,7 @@ | |||
314 | 43 | std::shared_ptr<Renderer> const& renderer, | 43 | std::shared_ptr<Renderer> const& renderer, |
315 | 44 | std::shared_ptr<CompositorReport> const& report); | 44 | std::shared_ptr<CompositorReport> const& report); |
316 | 45 | 45 | ||
318 | 46 | void composite(SceneElementSequence&& scene_sequence) override; | 46 | int composite(SceneElementSequence&& scene_sequence) override; |
319 | 47 | 47 | ||
320 | 48 | private: | 48 | private: |
321 | 49 | graphics::DisplayBuffer& display_buffer; | 49 | graphics::DisplayBuffer& display_buffer; |
322 | 50 | 50 | ||
323 | === modified file 'src/server/compositor/multi_threaded_compositor.cpp' | |||
324 | --- src/server/compositor/multi_threaded_compositor.cpp 2016-02-09 16:40:57 +0000 | |||
325 | +++ src/server/compositor/multi_threaded_compositor.cpp 2016-02-11 14:50:57 +0000 | |||
326 | @@ -131,14 +131,15 @@ | |||
327 | 131 | * frames_scheduled indicates the number of frames that are scheduled | 131 | * frames_scheduled indicates the number of frames that are scheduled |
328 | 132 | * to ensure all surfaces' queues are fully drained. | 132 | * to ensure all surfaces' queues are fully drained. |
329 | 133 | */ | 133 | */ |
331 | 134 | frames_scheduled--; | 134 | int pending = --frames_scheduled; |
332 | 135 | not_posted_yet = false; | 135 | not_posted_yet = false; |
333 | 136 | lock.unlock(); | 136 | lock.unlock(); |
334 | 137 | 137 | ||
335 | 138 | for (auto& tuple : compositors) | 138 | for (auto& tuple : compositors) |
336 | 139 | { | 139 | { |
337 | 140 | auto& compositor = std::get<1>(tuple); | 140 | auto& compositor = std::get<1>(tuple); |
339 | 141 | compositor->composite(scene->scene_elements_for(compositor.get())); | 141 | auto max_pending_frames = compositor->composite(scene->scene_elements_for(compositor.get())); |
340 | 142 | if (pending < max_pending_frames) pending = max_pending_frames; | ||
341 | 142 | } | 143 | } |
342 | 143 | group.post(); | 144 | group.post(); |
343 | 144 | 145 | ||
344 | @@ -161,15 +162,6 @@ | |||
345 | 161 | * important to re-count number of frames pending, separately | 162 | * important to re-count number of frames pending, separately |
346 | 162 | * to the initial scene_elements_for()... | 163 | * to the initial scene_elements_for()... |
347 | 163 | */ | 164 | */ |
348 | 164 | int pending = 0; | ||
349 | 165 | for (auto& compositor : compositors) | ||
350 | 166 | { | ||
351 | 167 | auto const comp_id = std::get<1>(compositor).get(); | ||
352 | 168 | int pend = scene->frames_pending(comp_id); | ||
353 | 169 | if (pend > pending) | ||
354 | 170 | pending = pend; | ||
355 | 171 | } | ||
356 | 172 | |||
357 | 173 | if (pending > frames_scheduled) | 165 | if (pending > frames_scheduled) |
358 | 174 | frames_scheduled = pending; | 166 | frames_scheduled = pending; |
359 | 175 | } | 167 | } |
360 | 176 | 168 | ||
361 | === modified file 'src/server/scene/rendering_tracker.cpp' | |||
362 | --- src/server/scene/rendering_tracker.cpp 2016-01-29 08:18:22 +0000 | |||
363 | +++ src/server/scene/rendering_tracker.cpp 2016-02-11 14:50:57 +0000 | |||
364 | @@ -80,6 +80,15 @@ | |||
365 | 80 | return occlusions.find(cid) == occlusions.end(); | 80 | return occlusions.find(cid) == occlusions.end(); |
366 | 81 | } | 81 | } |
367 | 82 | 82 | ||
368 | 83 | int ms::RenderingTracker::pending_buffers_for(compositor::CompositorID cid) const | ||
369 | 84 | { | ||
370 | 85 | if (auto const surface = weak_surface.lock()) | ||
371 | 86 | return surface->buffers_ready_for_compositor(cid); | ||
372 | 87 | else | ||
373 | 88 | return 0; | ||
374 | 89 | } | ||
375 | 90 | |||
376 | 91 | |||
377 | 83 | bool ms::RenderingTracker::occluded_in_all_active_compositors() | 92 | bool ms::RenderingTracker::occluded_in_all_active_compositors() |
378 | 84 | { | 93 | { |
379 | 85 | return occlusions == active_compositors_; | 94 | return occlusions == active_compositors_; |
380 | 86 | 95 | ||
381 | === modified file 'src/server/scene/rendering_tracker.h' | |||
382 | --- src/server/scene/rendering_tracker.h 2016-01-29 08:18:22 +0000 | |||
383 | +++ src/server/scene/rendering_tracker.h 2016-02-11 14:50:57 +0000 | |||
384 | @@ -43,6 +43,7 @@ | |||
385 | 43 | void occluded_in(compositor::CompositorID cid); | 43 | void occluded_in(compositor::CompositorID cid); |
386 | 44 | void active_compositors(std::set<compositor::CompositorID> const& cids); | 44 | void active_compositors(std::set<compositor::CompositorID> const& cids); |
387 | 45 | bool is_exposed_in(compositor::CompositorID cid) const; | 45 | bool is_exposed_in(compositor::CompositorID cid) const; |
388 | 46 | int pending_buffers_for(compositor::CompositorID cid) const; | ||
389 | 46 | 47 | ||
390 | 47 | private: | 48 | private: |
391 | 48 | bool occluded_in_all_active_compositors(); | 49 | bool occluded_in_all_active_compositors(); |
392 | 49 | 50 | ||
393 | === modified file 'src/server/scene/surface_stack.cpp' | |||
394 | --- src/server/scene/surface_stack.cpp 2016-01-29 08:18:22 +0000 | |||
395 | +++ src/server/scene/surface_stack.cpp 2016-02-11 14:50:57 +0000 | |||
396 | @@ -73,6 +73,11 @@ | |||
397 | 73 | tracker->occluded_in(cid); | 73 | tracker->occluded_in(cid); |
398 | 74 | } | 74 | } |
399 | 75 | 75 | ||
400 | 76 | int pending_buffers() const override | ||
401 | 77 | { | ||
402 | 78 | return tracker->pending_buffers_for(cid); | ||
403 | 79 | } | ||
404 | 80 | |||
405 | 76 | std::unique_ptr<mc::Decoration> decoration() const override | 81 | std::unique_ptr<mc::Decoration> decoration() const override |
406 | 77 | { | 82 | { |
407 | 78 | return std::make_unique<mc::Decoration>(mc::Decoration::Type::surface, surface_name); | 83 | return std::make_unique<mc::Decoration>(mc::Decoration::Type::surface, surface_name); |
408 | @@ -108,6 +113,11 @@ | |||
409 | 108 | { | 113 | { |
410 | 109 | } | 114 | } |
411 | 110 | 115 | ||
412 | 116 | int pending_buffers() const override | ||
413 | 117 | { | ||
414 | 118 | return 0; | ||
415 | 119 | } | ||
416 | 120 | |||
417 | 111 | std::unique_ptr<mc::Decoration> decoration() const override | 121 | std::unique_ptr<mc::Decoration> decoration() const override |
418 | 112 | { | 122 | { |
419 | 113 | return std::make_unique<mc::Decoration>(); | 123 | return std::make_unique<mc::Decoration>(); |
420 | @@ -154,30 +164,6 @@ | |||
421 | 154 | return elements; | 164 | return elements; |
422 | 155 | } | 165 | } |
423 | 156 | 166 | ||
424 | 157 | int ms::SurfaceStack::frames_pending(mc::CompositorID id) const | ||
425 | 158 | { | ||
426 | 159 | RecursiveReadLock lg(guard); | ||
427 | 160 | |||
428 | 161 | int result = scene_changed ? 1 : 0; | ||
429 | 162 | for (auto const& surface : surfaces) | ||
430 | 163 | { | ||
431 | 164 | if (surface->visible()) | ||
432 | 165 | { | ||
433 | 166 | auto const tracker = rendering_trackers.find(surface.get()); | ||
434 | 167 | if (tracker != rendering_trackers.end() && tracker->second->is_exposed_in(id)) | ||
435 | 168 | { | ||
436 | 169 | // Note that we ask the surface and not a Renderable. | ||
437 | 170 | // This is because we don't want to waste time and resources | ||
438 | 171 | // on a snapshot till we're sure we need it... | ||
439 | 172 | int ready = surface->buffers_ready_for_compositor(id); | ||
440 | 173 | if (ready > result) | ||
441 | 174 | result = ready; | ||
442 | 175 | } | ||
443 | 176 | } | ||
444 | 177 | } | ||
445 | 178 | return result; | ||
446 | 179 | } | ||
447 | 180 | |||
448 | 181 | void ms::SurfaceStack::register_compositor(mc::CompositorID cid) | 167 | void ms::SurfaceStack::register_compositor(mc::CompositorID cid) |
449 | 182 | { | 168 | { |
450 | 183 | RecursiveWriteLock lg(guard); | 169 | RecursiveWriteLock lg(guard); |
451 | 184 | 170 | ||
452 | === modified file 'src/server/scene/surface_stack.h' | |||
453 | --- src/server/scene/surface_stack.h 2016-01-29 08:18:22 +0000 | |||
454 | +++ src/server/scene/surface_stack.h 2016-02-11 14:50:57 +0000 | |||
455 | @@ -74,7 +74,6 @@ | |||
456 | 74 | 74 | ||
457 | 75 | // From Scene | 75 | // From Scene |
458 | 76 | compositor::SceneElementSequence scene_elements_for(compositor::CompositorID id) override; | 76 | compositor::SceneElementSequence scene_elements_for(compositor::CompositorID id) override; |
459 | 77 | int frames_pending(compositor::CompositorID) const override; | ||
460 | 78 | void register_compositor(compositor::CompositorID id) override; | 77 | void register_compositor(compositor::CompositorID id) override; |
461 | 79 | void unregister_compositor(compositor::CompositorID id) override; | 78 | void unregister_compositor(compositor::CompositorID id) override; |
462 | 80 | 79 | ||
463 | 81 | 80 | ||
464 | === modified file 'tests/acceptance-tests/test_buffer_stream_arrangement.cpp' | |||
465 | --- tests/acceptance-tests/test_buffer_stream_arrangement.cpp 2016-01-29 08:18:22 +0000 | |||
466 | +++ tests/acceptance-tests/test_buffer_stream_arrangement.cpp 2016-02-11 14:50:57 +0000 | |||
467 | @@ -167,10 +167,10 @@ | |||
468 | 167 | { | 167 | { |
469 | 168 | } | 168 | } |
470 | 169 | 169 | ||
472 | 170 | void composite(mc::SceneElementSequence&& scene_sequence) override | 170 | int composite(mc::SceneElementSequence&& scene_sequence) override |
473 | 171 | { | 171 | { |
474 | 172 | ordering->note_scene_element_sequence(scene_sequence); | 172 | ordering->note_scene_element_sequence(scene_sequence); |
476 | 173 | wrapped->composite(std::move(scene_sequence)); | 173 | return wrapped->composite(std::move(scene_sequence)); |
477 | 174 | } | 174 | } |
478 | 175 | 175 | ||
479 | 176 | std::shared_ptr<mc::DisplayBufferCompositor> const wrapped; | 176 | std::shared_ptr<mc::DisplayBufferCompositor> const wrapped; |
480 | 177 | 177 | ||
481 | === modified file 'tests/acceptance-tests/test_client_scaling.cpp' | |||
482 | --- tests/acceptance-tests/test_client_scaling.cpp 2016-01-29 08:18:22 +0000 | |||
483 | +++ tests/acceptance-tests/test_client_scaling.cpp 2016-02-11 14:50:57 +0000 | |||
484 | @@ -120,10 +120,11 @@ | |||
485 | 120 | { | 120 | { |
486 | 121 | } | 121 | } |
487 | 122 | 122 | ||
489 | 123 | void composite(mc::SceneElementSequence&& seq) | 123 | int composite(mc::SceneElementSequence&& seq) |
490 | 124 | { | 124 | { |
491 | 125 | watch->note_renderable_sizes(this, seq); | 125 | watch->note_renderable_sizes(this, seq); |
492 | 126 | std::this_thread::yield(); | 126 | std::this_thread::yield(); |
493 | 127 | return 0; | ||
494 | 127 | } | 128 | } |
495 | 128 | 129 | ||
496 | 129 | std::shared_ptr<SizeWatcher> const watch; | 130 | std::shared_ptr<SizeWatcher> const watch; |
497 | 130 | 131 | ||
498 | === modified file 'tests/acceptance-tests/test_render_override.cpp' | |||
499 | --- tests/acceptance-tests/test_render_override.cpp 2015-06-17 05:20:42 +0000 | |||
500 | +++ tests/acceptance-tests/test_render_override.cpp 2016-02-11 14:50:57 +0000 | |||
501 | @@ -74,7 +74,7 @@ | |||
502 | 74 | { | 74 | { |
503 | 75 | } | 75 | } |
504 | 76 | 76 | ||
506 | 77 | void composite(mc::SceneElementSequence&& sequence) override | 77 | int composite(mc::SceneElementSequence&& sequence) override |
507 | 78 | { | 78 | { |
508 | 79 | for(auto const& element : sequence) | 79 | for(auto const& element : sequence) |
509 | 80 | { | 80 | { |
510 | @@ -82,6 +82,8 @@ | |||
511 | 82 | renderable->buffer(); //consume buffer to stop compositor from spinning | 82 | renderable->buffer(); //consume buffer to stop compositor from spinning |
512 | 83 | tracker->surface_rendered_with_size(renderable->screen_position().size); | 83 | tracker->surface_rendered_with_size(renderable->screen_position().size); |
513 | 84 | } | 84 | } |
514 | 85 | |||
515 | 86 | return 0; | ||
516 | 85 | } | 87 | } |
517 | 86 | private: | 88 | private: |
518 | 87 | std::shared_ptr<CompositionTracker> const tracker; | 89 | std::shared_ptr<CompositionTracker> const tracker; |
519 | 88 | 90 | ||
520 | === modified file 'tests/include/mir/test/doubles/stub_scene.h' | |||
521 | --- tests/include/mir/test/doubles/stub_scene.h 2015-02-22 07:46:25 +0000 | |||
522 | +++ tests/include/mir/test/doubles/stub_scene.h 2016-02-11 14:50:57 +0000 | |||
523 | @@ -36,10 +36,6 @@ | |||
524 | 36 | { | 36 | { |
525 | 37 | return {}; | 37 | return {}; |
526 | 38 | } | 38 | } |
527 | 39 | int frames_pending(compositor::CompositorID) const override | ||
528 | 40 | { | ||
529 | 41 | return 0; | ||
530 | 42 | } | ||
531 | 43 | void register_compositor(compositor::CompositorID) override | 39 | void register_compositor(compositor::CompositorID) override |
532 | 44 | { | 40 | { |
533 | 45 | } | 41 | } |
534 | 46 | 42 | ||
535 | === modified file 'tests/include/mir/test/doubles/stub_scene_element.h' | |||
536 | --- tests/include/mir/test/doubles/stub_scene_element.h 2015-06-17 05:20:42 +0000 | |||
537 | +++ tests/include/mir/test/doubles/stub_scene_element.h 2016-02-11 14:50:57 +0000 | |||
538 | @@ -56,6 +56,11 @@ | |||
539 | 56 | { | 56 | { |
540 | 57 | } | 57 | } |
541 | 58 | 58 | ||
542 | 59 | int pending_buffers() const override | ||
543 | 60 | { | ||
544 | 61 | return 0; | ||
545 | 62 | } | ||
546 | 63 | |||
547 | 59 | std::unique_ptr<compositor::Decoration> decoration() const override | 64 | std::unique_ptr<compositor::Decoration> decoration() const override |
548 | 60 | { | 65 | { |
549 | 61 | return nullptr; | 66 | return nullptr; |
550 | 62 | 67 | ||
551 | === modified file 'tests/integration-tests/test_server_shutdown.cpp' | |||
552 | --- tests/integration-tests/test_server_shutdown.cpp 2016-01-29 08:18:22 +0000 | |||
553 | +++ tests/integration-tests/test_server_shutdown.cpp 2016-02-11 14:50:57 +0000 | |||
554 | @@ -189,7 +189,7 @@ | |||
555 | 189 | { | 189 | { |
556 | 190 | struct ExceptionThrowingDisplayBufferCompositor : mc::DisplayBufferCompositor | 190 | struct ExceptionThrowingDisplayBufferCompositor : mc::DisplayBufferCompositor |
557 | 191 | { | 191 | { |
559 | 192 | void composite(mc::SceneElementSequence&&) override | 192 | int composite(mc::SceneElementSequence&&) override |
560 | 193 | { | 193 | { |
561 | 194 | throw std::runtime_error("ExceptionThrowingDisplayBufferCompositor"); | 194 | throw std::runtime_error("ExceptionThrowingDisplayBufferCompositor"); |
562 | 195 | } | 195 | } |
563 | 196 | 196 | ||
564 | === modified file 'tests/unit-tests/compositor/test_compositing_screencast.cpp' | |||
565 | --- tests/unit-tests/compositor/test_compositing_screencast.cpp 2016-02-01 22:53:06 +0000 | |||
566 | +++ tests/unit-tests/compositor/test_compositing_screencast.cpp 2016-02-11 14:50:57 +0000 | |||
567 | @@ -118,9 +118,10 @@ | |||
568 | 118 | 118 | ||
569 | 119 | struct MockDisplayBufferCompositor : mc::DisplayBufferCompositor | 119 | struct MockDisplayBufferCompositor : mc::DisplayBufferCompositor |
570 | 120 | { | 120 | { |
572 | 121 | void composite(mc::SceneElementSequence&& seq) | 121 | int composite(mc::SceneElementSequence&& seq) |
573 | 122 | { | 122 | { |
574 | 123 | composite_(seq); | 123 | composite_(seq); |
575 | 124 | return 0; | ||
576 | 124 | } | 125 | } |
577 | 125 | 126 | ||
578 | 126 | MOCK_METHOD1(composite_, void(mc::SceneElementSequence&)); | 127 | MOCK_METHOD1(composite_, void(mc::SceneElementSequence&)); |
579 | @@ -134,9 +135,9 @@ | |||
580 | 134 | { | 135 | { |
581 | 135 | } | 136 | } |
582 | 136 | 137 | ||
584 | 137 | void composite(mc::SceneElementSequence&& elements) | 138 | int composite(mc::SceneElementSequence&& elements) |
585 | 138 | { | 139 | { |
587 | 139 | comp.composite(std::move(elements)); | 140 | return comp.composite(std::move(elements)); |
588 | 140 | } | 141 | } |
589 | 141 | 142 | ||
590 | 142 | private: | 143 | private: |
591 | 143 | 144 | ||
592 | === modified file 'tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp' | |||
593 | --- tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2016-01-29 08:18:22 +0000 | |||
594 | +++ tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2016-02-11 14:50:57 +0000 | |||
595 | @@ -48,6 +48,7 @@ | |||
596 | 48 | 48 | ||
597 | 49 | namespace mt = mir::test; | 49 | namespace mt = mir::test; |
598 | 50 | namespace mtd = mir::test::doubles; | 50 | namespace mtd = mir::test::doubles; |
599 | 51 | using namespace testing; | ||
600 | 51 | 52 | ||
601 | 52 | namespace | 53 | namespace |
602 | 53 | { | 54 | { |
603 | @@ -72,6 +73,11 @@ | |||
604 | 72 | { | 73 | { |
605 | 73 | } | 74 | } |
606 | 74 | 75 | ||
607 | 76 | int pending_buffers() const override | ||
608 | 77 | { | ||
609 | 78 | return 0; | ||
610 | 79 | } | ||
611 | 80 | |||
612 | 75 | std::unique_ptr<mc::Decoration> decoration() const override | 81 | std::unique_ptr<mc::Decoration> decoration() const override |
613 | 76 | { | 82 | { |
614 | 77 | return nullptr; | 83 | return nullptr; |
615 | @@ -97,7 +103,6 @@ | |||
616 | 97 | big(std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{5, 10},{100, 200}})), | 103 | big(std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{5, 10},{100, 200}})), |
617 | 98 | fullscreen(std::make_shared<mtd::FakeRenderable>(screen)) | 104 | fullscreen(std::make_shared<mtd::FakeRenderable>(screen)) |
618 | 99 | { | 105 | { |
619 | 100 | using namespace testing; | ||
620 | 101 | ON_CALL(display_buffer, orientation()) | 106 | ON_CALL(display_buffer, orientation()) |
621 | 102 | .WillByDefault(Return(mir_orientation_normal)); | 107 | .WillByDefault(Return(mir_orientation_normal)); |
622 | 103 | ON_CALL(display_buffer, view_area()) | 108 | ON_CALL(display_buffer, view_area()) |
623 | @@ -106,7 +111,7 @@ | |||
624 | 106 | .WillByDefault(Return(false)); | 111 | .WillByDefault(Return(false)); |
625 | 107 | } | 112 | } |
626 | 108 | 113 | ||
628 | 109 | testing::NiceMock<mtd::MockRenderer> mock_renderer; | 114 | NiceMock<mtd::MockRenderer> mock_renderer; |
629 | 110 | geom::Rectangle screen{{0, 0}, {1366, 768}}; | 115 | geom::Rectangle screen{{0, 0}, {1366, 768}}; |
630 | 111 | testing::NiceMock<mtd::MockDisplayBuffer> display_buffer; | 116 | testing::NiceMock<mtd::MockDisplayBuffer> display_buffer; |
631 | 112 | std::shared_ptr<mtd::FakeRenderable> small; | 117 | std::shared_ptr<mtd::FakeRenderable> small; |
632 | @@ -132,7 +137,6 @@ | |||
633 | 132 | 137 | ||
634 | 133 | TEST_F(DefaultDisplayBufferCompositor, optimization_skips_composition) | 138 | TEST_F(DefaultDisplayBufferCompositor, optimization_skips_composition) |
635 | 134 | { | 139 | { |
636 | 135 | using namespace testing; | ||
637 | 136 | auto report = std::make_shared<mtd::MockCompositorReport>(); | 140 | auto report = std::make_shared<mtd::MockCompositorReport>(); |
638 | 137 | 141 | ||
639 | 138 | Sequence seq; | 142 | Sequence seq; |
640 | @@ -190,7 +194,6 @@ | |||
641 | 190 | 194 | ||
642 | 191 | TEST_F(DefaultDisplayBufferCompositor, calls_renderer_in_sequence) | 195 | TEST_F(DefaultDisplayBufferCompositor, calls_renderer_in_sequence) |
643 | 192 | { | 196 | { |
644 | 193 | using namespace testing; | ||
645 | 194 | Sequence render_seq; | 197 | Sequence render_seq; |
646 | 195 | EXPECT_CALL(mock_renderer, suspend()) | 198 | EXPECT_CALL(mock_renderer, suspend()) |
647 | 196 | .Times(0); | 199 | .Times(0); |
648 | @@ -215,7 +218,6 @@ | |||
649 | 215 | 218 | ||
650 | 216 | TEST_F(DefaultDisplayBufferCompositor, optimization_toggles_seamlessly) | 219 | TEST_F(DefaultDisplayBufferCompositor, optimization_toggles_seamlessly) |
651 | 217 | { | 220 | { |
652 | 218 | using namespace testing; | ||
653 | 219 | ON_CALL(display_buffer, view_area()) | 221 | ON_CALL(display_buffer, view_area()) |
654 | 220 | .WillByDefault(Return(screen)); | 222 | .WillByDefault(Return(screen)); |
655 | 221 | ON_CALL(display_buffer, orientation()) | 223 | ON_CALL(display_buffer, orientation()) |
656 | @@ -262,7 +264,6 @@ | |||
657 | 262 | 264 | ||
658 | 263 | TEST_F(DefaultDisplayBufferCompositor, occluded_surfaces_are_not_rendered) | 265 | TEST_F(DefaultDisplayBufferCompositor, occluded_surfaces_are_not_rendered) |
659 | 264 | { | 266 | { |
660 | 265 | using namespace testing; | ||
661 | 266 | EXPECT_CALL(display_buffer, view_area()) | 267 | EXPECT_CALL(display_buffer, view_area()) |
662 | 267 | .WillRepeatedly(Return(screen)); | 268 | .WillRepeatedly(Return(screen)); |
663 | 268 | EXPECT_CALL(display_buffer, orientation()) | 269 | EXPECT_CALL(display_buffer, orientation()) |
664 | @@ -305,13 +306,12 @@ | |||
665 | 305 | MOCK_CONST_METHOD0(decoration, std::unique_ptr<mc::Decoration>()); | 306 | MOCK_CONST_METHOD0(decoration, std::unique_ptr<mc::Decoration>()); |
666 | 306 | MOCK_METHOD0(rendered, void()); | 307 | MOCK_METHOD0(rendered, void()); |
667 | 307 | MOCK_METHOD0(occluded, void()); | 308 | MOCK_METHOD0(occluded, void()); |
668 | 309 | MOCK_CONST_METHOD0(pending_buffers, int()); | ||
669 | 308 | }; | 310 | }; |
670 | 309 | } | 311 | } |
671 | 310 | 312 | ||
672 | 311 | TEST_F(DefaultDisplayBufferCompositor, marks_rendered_scene_elements) | 313 | TEST_F(DefaultDisplayBufferCompositor, marks_rendered_scene_elements) |
673 | 312 | { | 314 | { |
674 | 313 | using namespace testing; | ||
675 | 314 | |||
676 | 315 | auto element0_rendered = std::make_shared<NiceMock<MockSceneElement>>( | 315 | auto element0_rendered = std::make_shared<NiceMock<MockSceneElement>>( |
677 | 316 | std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{99,99},{2,2}})); | 316 | std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{99,99},{2,2}})); |
678 | 317 | auto element1_rendered = std::make_shared<NiceMock<MockSceneElement>>( | 317 | auto element1_rendered = std::make_shared<NiceMock<MockSceneElement>>( |
679 | @@ -330,8 +330,6 @@ | |||
680 | 330 | 330 | ||
681 | 331 | TEST_F(DefaultDisplayBufferCompositor, marks_occluded_scene_elements) | 331 | TEST_F(DefaultDisplayBufferCompositor, marks_occluded_scene_elements) |
682 | 332 | { | 332 | { |
683 | 333 | using namespace testing; | ||
684 | 334 | |||
685 | 335 | auto element0_occluded = std::make_shared<NiceMock<MockSceneElement>>( | 333 | auto element0_occluded = std::make_shared<NiceMock<MockSceneElement>>( |
686 | 336 | std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{10,10},{20,20}})); | 334 | std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{10,10},{20,20}})); |
687 | 337 | auto element1_rendered = std::make_shared<NiceMock<MockSceneElement>>( | 335 | auto element1_rendered = std::make_shared<NiceMock<MockSceneElement>>( |
688 | @@ -351,3 +349,39 @@ | |||
689 | 351 | compositor.composite({element0_occluded, element1_rendered, element2_occluded}); | 349 | compositor.composite({element0_occluded, element1_rendered, element2_occluded}); |
690 | 352 | } | 350 | } |
691 | 353 | 351 | ||
692 | 352 | TEST_F(DefaultDisplayBufferCompositor, reports_pending_frames_accurately) | ||
693 | 353 | { | ||
694 | 354 | auto const element = std::make_shared<NiceMock<MockSceneElement>>( | ||
695 | 355 | std::make_shared<mtd::FakeRenderable>(geom::Rectangle{{10,10},{20,20}})); | ||
696 | 356 | |||
697 | 357 | mc::DefaultDisplayBufferCompositor compositor( | ||
698 | 358 | display_buffer, | ||
699 | 359 | mt::fake_shared(mock_renderer), | ||
700 | 360 | mr::null_compositor_report()); | ||
701 | 361 | |||
702 | 362 | EXPECT_THAT(compositor.composite({element}), Eq(0)); | ||
703 | 363 | |||
704 | 364 | auto const pending_frames_before = 3; | ||
705 | 365 | auto const pending_frames_after = pending_frames_before-1; | ||
706 | 366 | |||
707 | 367 | EXPECT_CALL(*element, pending_buffers()).WillOnce(Return(pending_frames_after)); | ||
708 | 368 | EXPECT_THAT(compositor.composite({element}), Eq(pending_frames_after)); | ||
709 | 369 | } | ||
710 | 370 | |||
711 | 371 | TEST_F(DefaultDisplayBufferCompositor, doesnt_count_pending_frames_from_occluded_surfaces) | ||
712 | 372 | { | ||
713 | 373 | auto const element = std::make_shared<NiceMock<MockSceneElement>>( | ||
714 | 374 | std::make_shared<mtd::FakeRenderable>(geom::Rectangle{screen.bottom_right(),{20,20}})); | ||
715 | 375 | |||
716 | 376 | mc::DefaultDisplayBufferCompositor compositor( | ||
717 | 377 | display_buffer, | ||
718 | 378 | mt::fake_shared(mock_renderer), | ||
719 | 379 | mr::null_compositor_report()); | ||
720 | 380 | |||
721 | 381 | EXPECT_THAT(compositor.composite({element}), Eq(0)); | ||
722 | 382 | |||
723 | 383 | auto const pending_frames = 3; | ||
724 | 384 | ON_CALL(*element, pending_buffers()).WillByDefault(Return(pending_frames)); | ||
725 | 385 | |||
726 | 386 | EXPECT_THAT(compositor.composite({element}), Eq(0)); | ||
727 | 387 | } | ||
728 | 354 | 388 | ||
729 | === modified file 'tests/unit-tests/compositor/test_multi_threaded_compositor.cpp' | |||
730 | --- tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2016-02-01 09:42:10 +0000 | |||
731 | +++ tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2016-02-11 14:50:57 +0000 | |||
732 | @@ -96,8 +96,8 @@ | |||
733 | 96 | class StubScene : public mtd::StubScene | 96 | class StubScene : public mtd::StubScene |
734 | 97 | { | 97 | { |
735 | 98 | public: | 98 | public: |
738 | 99 | StubScene() | 99 | StubScene() : |
739 | 100 | : pending{0}, throw_on_add_observer_{false} | 100 | throw_on_add_observer_{false} |
740 | 101 | { | 101 | { |
741 | 102 | } | 102 | } |
742 | 103 | 103 | ||
743 | @@ -136,19 +136,7 @@ | |||
744 | 136 | throw_on_add_observer_ = flag; | 136 | throw_on_add_observer_ = flag; |
745 | 137 | } | 137 | } |
746 | 138 | 138 | ||
747 | 139 | int frames_pending(mc::CompositorID) const override | ||
748 | 140 | { | ||
749 | 141 | return pending; | ||
750 | 142 | } | ||
751 | 143 | |||
752 | 144 | void set_pending(int n) | ||
753 | 145 | { | ||
754 | 146 | pending = n; | ||
755 | 147 | observer->scene_changed(); | ||
756 | 148 | } | ||
757 | 149 | |||
758 | 150 | private: | 139 | private: |
759 | 151 | std::atomic<int> pending; | ||
760 | 152 | std::mutex observer_mutex; | 140 | std::mutex observer_mutex; |
761 | 153 | std::shared_ptr<ms::Observer> observer; | 141 | std::shared_ptr<ms::Observer> observer; |
762 | 154 | bool throw_on_add_observer_; | 142 | bool throw_on_add_observer_; |
763 | @@ -157,20 +145,21 @@ | |||
764 | 157 | class RecordingDisplayBufferCompositor : public mc::DisplayBufferCompositor | 145 | class RecordingDisplayBufferCompositor : public mc::DisplayBufferCompositor |
765 | 158 | { | 146 | { |
766 | 159 | public: | 147 | public: |
768 | 160 | RecordingDisplayBufferCompositor(std::function<void()> const& mark_render_buffer) | 148 | RecordingDisplayBufferCompositor(std::function<int()> const& mark_render_buffer) |
769 | 161 | : mark_render_buffer{mark_render_buffer} | 149 | : mark_render_buffer{mark_render_buffer} |
770 | 162 | { | 150 | { |
771 | 163 | } | 151 | } |
772 | 164 | 152 | ||
774 | 165 | void composite(mc::SceneElementSequence&&) | 153 | int composite(mc::SceneElementSequence&&) |
775 | 166 | { | 154 | { |
777 | 167 | mark_render_buffer(); | 155 | auto const result = mark_render_buffer(); |
778 | 168 | /* Reduce run-time under valgrind */ | 156 | /* Reduce run-time under valgrind */ |
779 | 169 | std::this_thread::yield(); | 157 | std::this_thread::yield(); |
780 | 158 | return result; | ||
781 | 170 | } | 159 | } |
782 | 171 | 160 | ||
783 | 172 | private: | 161 | private: |
785 | 173 | std::function<void()> const mark_render_buffer; | 162 | std::function<int()> const mark_render_buffer; |
786 | 174 | }; | 163 | }; |
787 | 175 | 164 | ||
788 | 176 | 165 | ||
789 | @@ -182,12 +171,12 @@ | |||
790 | 182 | auto raw = new RecordingDisplayBufferCompositor{ | 171 | auto raw = new RecordingDisplayBufferCompositor{ |
791 | 183 | [&display_buffer,this]() | 172 | [&display_buffer,this]() |
792 | 184 | { | 173 | { |
794 | 185 | mark_render_buffer(display_buffer); | 174 | return mark_render_buffer(display_buffer); |
795 | 186 | }}; | 175 | }}; |
796 | 187 | return std::unique_ptr<RecordingDisplayBufferCompositor>(raw); | 176 | return std::unique_ptr<RecordingDisplayBufferCompositor>(raw); |
797 | 188 | } | 177 | } |
798 | 189 | 178 | ||
800 | 190 | void mark_render_buffer(mg::DisplayBuffer& display_buffer) | 179 | int mark_render_buffer(mg::DisplayBuffer& display_buffer) |
801 | 191 | { | 180 | { |
802 | 192 | std::lock_guard<std::mutex> lk{m}; | 181 | std::lock_guard<std::mutex> lk{m}; |
803 | 193 | 182 | ||
804 | @@ -196,6 +185,8 @@ | |||
805 | 196 | 185 | ||
806 | 197 | ++records[&display_buffer].first; | 186 | ++records[&display_buffer].first; |
807 | 198 | records[&display_buffer].second.insert(std::this_thread::get_id()); | 187 | records[&display_buffer].second.insert(std::this_thread::get_id()); |
808 | 188 | |||
809 | 189 | return pending; | ||
810 | 199 | } | 190 | } |
811 | 200 | 191 | ||
812 | 201 | bool enough_records_gathered(unsigned int nbuffers, unsigned int min_record_count = 1000) | 192 | bool enough_records_gathered(unsigned int nbuffers, unsigned int min_record_count = 1000) |
813 | @@ -264,7 +255,10 @@ | |||
814 | 264 | return true; | 255 | return true; |
815 | 265 | } | 256 | } |
816 | 266 | 257 | ||
817 | 258 | void set_pending(int n) { pending = n; } | ||
818 | 259 | |||
819 | 267 | private: | 260 | private: |
820 | 261 | std::atomic<int> pending{0}; | ||
821 | 268 | std::mutex m; | 262 | std::mutex m; |
822 | 269 | typedef std::pair<unsigned int, std::unordered_set<std::thread::id>> Record; | 263 | typedef std::pair<unsigned int, std::unordered_set<std::thread::id>> Record; |
823 | 270 | std::unordered_map<mg::DisplayBuffer*,Record> records; | 264 | std::unordered_map<mg::DisplayBuffer*,Record> records; |
824 | @@ -278,11 +272,12 @@ | |||
825 | 278 | { | 272 | { |
826 | 279 | } | 273 | } |
827 | 280 | 274 | ||
829 | 281 | void composite(mc::SceneElementSequence&&) override | 275 | int composite(mc::SceneElementSequence&&) override |
830 | 282 | { | 276 | { |
831 | 283 | fake_surface_update(); | 277 | fake_surface_update(); |
832 | 284 | /* Reduce run-time under valgrind */ | 278 | /* Reduce run-time under valgrind */ |
833 | 285 | std::this_thread::yield(); | 279 | std::this_thread::yield(); |
834 | 280 | return 0; | ||
835 | 286 | } | 281 | } |
836 | 287 | 282 | ||
837 | 288 | private: | 283 | private: |
838 | @@ -331,6 +326,7 @@ | |||
839 | 331 | { | 326 | { |
840 | 332 | std::lock_guard<std::mutex> lock{thread_names_mutex}; | 327 | std::lock_guard<std::mutex> lock{thread_names_mutex}; |
841 | 333 | thread_names.emplace_back(mt::current_thread_name()); | 328 | thread_names.emplace_back(mt::current_thread_name()); |
842 | 329 | return 0; | ||
843 | 334 | }}; | 330 | }}; |
844 | 335 | return std::unique_ptr<RecordingDisplayBufferCompositor>(raw); | 331 | return std::unique_ptr<RecordingDisplayBufferCompositor>(raw); |
845 | 336 | } | 332 | } |
846 | @@ -595,7 +591,8 @@ | |||
847 | 595 | ASSERT_LT(retry, max_retries); | 591 | ASSERT_LT(retry, max_retries); |
848 | 596 | 592 | ||
849 | 597 | // Some surface queues up multiple frames | 593 | // Some surface queues up multiple frames |
851 | 598 | scene->set_pending(3); | 594 | factory->set_pending(3); |
852 | 595 | scene->emit_change_event(); | ||
853 | 599 | 596 | ||
854 | 600 | // Make sure they all get composited separately (2 + 3 more) | 597 | // Make sure they all get composited separately (2 + 3 more) |
855 | 601 | retry = 0; | 598 | retry = 0; |
856 | 602 | 599 | ||
857 | === modified file 'tests/unit-tests/scene/test_surface_stack.cpp' | |||
858 | --- tests/unit-tests/scene/test_surface_stack.cpp 2016-01-29 08:18:22 +0000 | |||
859 | +++ tests/unit-tests/scene/test_surface_stack.cpp 2016-02-11 14:50:57 +0000 | |||
860 | @@ -335,124 +335,6 @@ | |||
861 | 335 | EXPECT_EQ("username@hostname: ~/Documents", decor->name); | 335 | EXPECT_EQ("username@hostname: ~/Documents", decor->name); |
862 | 336 | } | 336 | } |
863 | 337 | 337 | ||
864 | 338 | TEST_F(SurfaceStack, scene_counts_pending_accurately) | ||
865 | 339 | { | ||
866 | 340 | using namespace testing; | ||
867 | 341 | ms::SurfaceStack stack{report}; | ||
868 | 342 | stack.register_compositor(this); | ||
869 | 343 | mtd::StubBuffer stub_buffer; | ||
870 | 344 | int ready = 0; | ||
871 | 345 | auto mock_queue = std::make_shared<testing::NiceMock<mtd::MockBufferBundle>>(); | ||
872 | 346 | ON_CALL(*mock_queue, buffers_ready_for_compositor(_)) | ||
873 | 347 | .WillByDefault(InvokeWithoutArgs([&]{return ready;})); | ||
874 | 348 | ON_CALL(*mock_queue, client_release(_)) | ||
875 | 349 | .WillByDefault(InvokeWithoutArgs([&]{ready++;})); | ||
876 | 350 | ON_CALL(*mock_queue, compositor_acquire(_)) | ||
877 | 351 | .WillByDefault(InvokeWithoutArgs([&]{ready--; return mt::fake_shared(stub_buffer); })); | ||
878 | 352 | |||
879 | 353 | auto surface = std::make_shared<ms::BasicSurface>( | ||
880 | 354 | std::string("stub"), | ||
881 | 355 | geom::Rectangle{{},{}}, | ||
882 | 356 | false, | ||
883 | 357 | std::make_shared<mc::BufferStreamSurfaces>(mock_queue), | ||
884 | 358 | std::shared_ptr<mir::input::InputChannel>(), | ||
885 | 359 | std::shared_ptr<mir::input::InputSender>(), | ||
886 | 360 | std::shared_ptr<mg::CursorImage>(), | ||
887 | 361 | report); | ||
888 | 362 | stack.add_surface(surface, default_params.input_mode); | ||
889 | 363 | surface->configure(mir_surface_attrib_visibility, | ||
890 | 364 | mir_surface_visibility_exposed); | ||
891 | 365 | |||
892 | 366 | EXPECT_EQ(0, stack.frames_pending(this)); | ||
893 | 367 | post_a_frame(*surface); | ||
894 | 368 | post_a_frame(*surface); | ||
895 | 369 | post_a_frame(*surface); | ||
896 | 370 | EXPECT_EQ(3, stack.frames_pending(this)); | ||
897 | 371 | |||
898 | 372 | for (int expect = 3; expect >= 0; --expect) | ||
899 | 373 | { | ||
900 | 374 | ASSERT_EQ(expect, stack.frames_pending(this)); | ||
901 | 375 | auto snap = stack.scene_elements_for(compositor_id); | ||
902 | 376 | for (auto& element : snap) | ||
903 | 377 | { | ||
904 | 378 | auto consumed = element->renderable()->buffer(); | ||
905 | 379 | } | ||
906 | 380 | } | ||
907 | 381 | } | ||
908 | 382 | |||
909 | 383 | TEST_F(SurfaceStack, scene_doesnt_count_pending_frames_from_occluded_surfaces) | ||
910 | 384 | { // Regression test for LP: #1418081 | ||
911 | 385 | using namespace testing; | ||
912 | 386 | |||
913 | 387 | ms::SurfaceStack stack{report}; | ||
914 | 388 | stack.register_compositor(this); | ||
915 | 389 | auto surface = std::make_shared<ms::BasicSurface>( | ||
916 | 390 | std::string("stub"), | ||
917 | 391 | geom::Rectangle{{},{}}, | ||
918 | 392 | false, | ||
919 | 393 | std::make_shared<mtd::StubBufferStream>(), | ||
920 | 394 | std::shared_ptr<mir::input::InputChannel>(), | ||
921 | 395 | std::shared_ptr<mir::input::InputSender>(), | ||
922 | 396 | std::shared_ptr<mg::CursorImage>(), | ||
923 | 397 | report); | ||
924 | 398 | |||
925 | 399 | stack.add_surface(surface, default_params.input_mode); | ||
926 | 400 | auto elements = stack.scene_elements_for(this); | ||
927 | 401 | for (auto const& elem : elements) | ||
928 | 402 | elem->occluded(); | ||
929 | 403 | |||
930 | 404 | EXPECT_EQ(0, stack.frames_pending(this)); | ||
931 | 405 | post_a_frame(*surface); | ||
932 | 406 | post_a_frame(*surface); | ||
933 | 407 | post_a_frame(*surface); | ||
934 | 408 | EXPECT_EQ(0, stack.frames_pending(this)); | ||
935 | 409 | } | ||
936 | 410 | |||
937 | 411 | TEST_F(SurfaceStack, scene_doesnt_count_pending_frames_from_partially_exposed_surfaces) | ||
938 | 412 | { // Regression test for LP: #1499039 | ||
939 | 413 | using namespace testing; | ||
940 | 414 | |||
941 | 415 | // Partially exposed means occluded in one compositor but not another | ||
942 | 416 | ms::SurfaceStack stack{report}; | ||
943 | 417 | auto const comp1 = reinterpret_cast<mc::CompositorID>(0); | ||
944 | 418 | auto const comp2 = reinterpret_cast<mc::CompositorID>(1); | ||
945 | 419 | |||
946 | 420 | stack.register_compositor(comp1); | ||
947 | 421 | stack.register_compositor(comp2); | ||
948 | 422 | auto surface = std::make_shared<ms::BasicSurface>( | ||
949 | 423 | std::string("stub"), | ||
950 | 424 | geom::Rectangle{{},{}}, | ||
951 | 425 | false, | ||
952 | 426 | std::make_shared<mtd::StubBufferStream>(), | ||
953 | 427 | std::shared_ptr<mir::input::InputChannel>(), | ||
954 | 428 | std::shared_ptr<mir::input::InputSender>(), | ||
955 | 429 | std::shared_ptr<mg::CursorImage>(), | ||
956 | 430 | report); | ||
957 | 431 | |||
958 | 432 | stack.add_surface(surface, default_params.input_mode); | ||
959 | 433 | post_a_frame(*surface); | ||
960 | 434 | post_a_frame(*surface); | ||
961 | 435 | post_a_frame(*surface); | ||
962 | 436 | |||
963 | 437 | EXPECT_EQ(3, stack.frames_pending(comp1)); | ||
964 | 438 | EXPECT_EQ(3, stack.frames_pending(comp2)); | ||
965 | 439 | |||
966 | 440 | auto elements = stack.scene_elements_for(comp1); | ||
967 | 441 | for (auto const& elem : elements) | ||
968 | 442 | { | ||
969 | 443 | elem->rendered(); | ||
970 | 444 | } | ||
971 | 445 | |||
972 | 446 | elements = stack.scene_elements_for(comp2); | ||
973 | 447 | for (auto const& elem : elements) | ||
974 | 448 | { | ||
975 | 449 | elem->occluded(); | ||
976 | 450 | } | ||
977 | 451 | |||
978 | 452 | EXPECT_EQ(3, stack.frames_pending(comp1)); | ||
979 | 453 | EXPECT_EQ(0, stack.frames_pending(comp2)); | ||
980 | 454 | } | ||
981 | 455 | |||
982 | 456 | TEST_F(SurfaceStack, surfaces_are_emitted_by_layer) | 338 | TEST_F(SurfaceStack, surfaces_are_emitted_by_layer) |
983 | 457 | { | 339 | { |
984 | 458 | using namespace testing; | 340 | using namespace testing; |
FAILED: Continuous integration, rev:3300 /mir-jenkins. ubuntu. com/job/ mir-ci/ 253/ /mir-jenkins. ubuntu. com/job/ build/41/ console /mir-jenkins. ubuntu. com/job/ build-0- fetch/47 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 43 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 43 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- advanced/ arch=amd64, compiler= gcc,platform= mesa,release= xenial/ 43/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- advanced/ arch=cross- armhf,compiler= gcc,platform= android, release= vivid+overlay/ 43 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- advanced/ arch=cross- armhf,compiler= gcc,platform= android, release= vivid+overlay/ 43/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- advanced/ arch=i386, compiler= gcc,platform= android, release= vivid+overlay/ 43 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- advanced/ arch=i386, compiler= gcc,platform= android, release= vivid+overlay/ 43/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- advanced/ arch=i386, compiler= gcc,platform= mesa,release= xenial/ 43/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 253/rebuild
https:/