Merge lp:~vanvugt/mir/unocclude into lp:mir
- unocclude
- Merge into development-branch
Status: | Rejected |
---|---|
Rejected by: | Daniel van Vugt |
Proposed branch: | lp:~vanvugt/mir/unocclude |
Merge into: | lp:mir |
Diff against target: |
512 lines (+6/-391) 8 files modified
src/server/compositor/CMakeLists.txt (+0/-1) src/server/compositor/default_display_buffer_compositor.cpp (+0/-2) src/server/compositor/occlusion.cpp (+0/-78) src/server/compositor/occlusion.h (+0/-37) tests/integration-tests/test_surface_first_frame_sync.cpp (+2/-2) tests/unit-tests/compositor/CMakeLists.txt (+0/-1) tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp (+4/-68) tests/unit-tests/compositor/test_occlusion.cpp (+0/-202) |
To merge this branch: | bzr merge lp:~vanvugt/mir/unocclude |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Kevin DuBois (community) | Abstain | ||
Robert Carr (community) | Disapprove | ||
Andreas Pokorny (community) | Needs Fixing | ||
Alberto Aguirre (community) | Disapprove | ||
Mir development team | Pending | ||
Review via email: mp+216690@code.launchpad.net |
Commit message
Delete the occlusion detection logic. It was never used where it was needed
(on mobile platforms) since platform-api never got fixed. It's also
fundamentally incompatible with the new goals of never blocking clients.
Then again, what we lose in performance we gain in simplicity.
Description of the change
Daniel van Vugt (vanvugt) wrote : | # |
Kevin DuBois (kdub) wrote : | # |
my thoughts:
pros:
* The occlusion detection made it difficult to unify the compositor's behavior around consuming buffers, which in turn made it unclear what the SwitchingBundle's responsibilities were. Consuming every buffer on a compositor pass makes it easier to get the switching logic right, and is at least a consistent requirement for a compositor writer.
* It does seem at odds to try to not consume a buffer, and never block a client.
cons:
* occlusion detection is valuable in reducing workload for the compositor (texture uploads)
* an obscured, visible client that can submit frames fast enough can keep the compositor recompositing the same pixels because of the 'uncomposited_
* loosing the logic puts us in a worse position if we're ever told to send 'occluded' messages to the client. (although this is a weak point due to YAGNI)
I am interested in what never got fixed in platform-api that made this code unused though.
An alternative compromise between the pros and cons could be to consume the buffer from all surfaces (unifying the behavior of the compositors/
I think that the benefits of doing this now outweigh the cost, especially as we refine the SurfaceStack/
Alberto Aguirre (albaguirre) wrote : | # |
" loosing the logic puts us in a worse position if we're ever told to send 'occluded' messages to the client."
We already have that need. It should go hand-in-hand with the non-blocking swap behavior IMHO.
Clients need to know when their surfaces are no longer visible so they can stop their rendering loop - this is either from having a surface that is no longer visible in any display or from true occlusion.
In the Unity8 case this is currently being handled by the app lifecycle since we don't currently produce those events.
Anpok has a branch in papi that would benefit from the occlusion logic:
https:/
We should still push through to get that branch merged.
Kevin DuBois (kdub) wrote : | # |
> " loosing the logic puts us in a worse position if we're ever told to send
> 'occluded' messages to the client."
>
> We already have that need. It should go hand-in-hand with the non-blocking
> swap behavior IMHO.
>
> Clients need to know when their surfaces are no longer visible so they can
> stop their rendering loop - this is either from having a surface that is no
> longer visible in any display or from true occlusion.
> In the Unity8 case this is currently being handled by the app lifecycle since
> we don't currently produce those events.
Yeah, but where the occlusion code is now is not in a good position to notify clients. Compositors should not have the job of notifying clients of their decisions, the clients should get notifications based on things going on with their associated ms::BasicSurface.
This pushes me to think we have to shift occlusion detection to SurfaceStack, as it seems the common place this could be done. The compositors sure have to have a role in submitting what sort of occlusion they should do, but I don't want the compositors slowed down by having to send IPC events.
Now of course, this is tricky, because we could have multiple compositors, but I think can be done as the SurfaceStack gets a bit smarter about what compositors are viewing the SurfaceStack.
Andreas Pokorny (andreas-pokorny) wrote : | # |
> This pushes me to think we have to shift occlusion detection to SurfaceStack,
> as it seems the common place this could be done. The compositors sure have to
> have a role in submitting what sort of occlusion they should do, but I don't
> want the compositors slowed down by having to send IPC events.
>
> Now of course, this is tricky, because we could have multiple compositors, but
> I think can be done as the SurfaceStack gets a bit smarter about what
> compositors are viewing the SurfaceStack.
+1
scene just needs to gain knowledge about the existing outputs. Their position within
the scene - the camera parameters. Those information could also be used to limit compositor
thread wakeups. Additionally that information is necessary to properly dispatch user input
within 3D shells.
We can solve the issue with decoration increasing the size of surfaces in a different way.
Treat decorations and window shadows as separate scene elements with a separate position
and size, that the shell adds to the scene..
Or maybe simpler: Extend the scenes occlusion logic with a filter-filter that filters out
false positives.
as a graphical effect that extend the size of surfaces, which
Daniel van Vugt (vanvugt) wrote : | # |
I think you're planning for the wrong approach. The renderer should never feed back directly to the client as it's just a /view/. The renderer shall never communicate with clients in any way. Instead we should indirectly observe that a client's become occluded. This is easy using BufferConsuming
Occlusion detection is designed to block clients that are not visible. That's it's purpose. If we're serious about making things non-blocking then it makes no sense to keep it as it only gets in the way (as mentioned here: https:/
Andreas Pokorny (andreas-pokorny) wrote : | # |
> I think you're planning for the wrong approach. The renderer should never feed
> back directly to the client as it's just a /view/. The renderer shall never
> communicate with clients in any way. Instead we should indirectly observe that
> a client's become occluded. This is easy using BufferConsuming
> observes physical frame completion - if and when lp:~vanvugt/mir/judder lands.
Hmm where did somebody indicate that the renderer should feed back to the clients?
> Occlusion detection is designed to block clients that are not visible. That's
> it's purpose. If we're serious about making things non-blocking then it makes
> no sense to keep it as it only gets in the way (as mentioned here:
> https:/
It also helps avoid unnecessary overdraw.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1568
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Kevin DuBois (kdub) wrote : | # |
> > I think you're planning for the wrong approach. The renderer should never
> feed
> > back directly to the client as it's just a /view/. The renderer shall never
> > communicate with clients in any way. Instead we should indirectly observe
> that
> > a client's become occluded. This is easy using BufferConsuming
> > observes physical frame completion - if and when lp:~vanvugt/mir/judder
> lands.
>
> Hmm where did somebody indicate that the renderer should feed back to the
> clients?
"Compositors should not have the job of notifying clients of their decisions, the clients should get notifications based on things going on with their associated ms::BasicSurface."
Yes, it seems like the thing we agree upon is that nothing in the compositor system (GLRenderer, DefaultDisplayB
The big objection seems to be the future needs of other parts of the system noted by Alberto and Andreas and the loss of the logic by its removal.
Daniel van Vugt (vanvugt) wrote : | # |
Hey I don't mind occlusion logic staying, but it is contradictory to non-blocking efforts. Choose one or the other.
I built the occlusion detection logic to block occluded clients. Its purpose is to block occluded clients from rendering, per bug 1227739. And it does that well.
If you choose both to have occlusion detection and non-blocking then you also require extra work (in pending proposals) to make them play together. Because the occlusion detection is only doing its job in blocking client rendering.
Robert Carr (robertcarr) wrote : | # |
>> > Occlusion detection is designed to block clients that are not visible. That's
>> > it's purpose. If we're serious about making things non-blocking then it makes
>> > no sense to keep it as it only gets in the way (as mentioned here:
>> > https:/
Occlusion detection can also be used to prevent overdraw. Clearly whether buffers are returned to the client is a different question than whether buffers are part of the composition pass.
This isn't so different than for example an XRender client under Compiz...client rendering isnt blocked by compositor consumption at all (at least not in the serial queue frame consumption style we have)! Still Compiz will choose to not paint occluded windows. We improve this model by enforcing synchronization while clients are painted on screen, and are free to break this lockstep synchronization guarantee when clients are not rendered.
>> Hey I don't mind occlusion logic staying, but it is contradictory to non-blocking efforts. Choose one or
>> the other.
Not if you allow framedropping for unrendered surfaces.
Daniel van Vugt (vanvugt) wrote : | # |
Heh. I'm not bothered either way. In fact, rather amused that other people are defending my code against deletion from myself.
Kevin DuBois (kdub) wrote : | # |
I'm still for having the occlusion algorithm as something that's set by the compositing system, but if notifications are to go out about occluded surfaces, that should be something sent from the Scene system, not the compositor. Anyways, given the review comments, it seems that this will be explored differently, so abstain.
Alberto Aguirre (albaguirre) wrote : | # |
> I'm still for having the occlusion algorithm as something that's set by the
> compositing system, but if notifications are to go out about occluded
> surfaces, that should be something sent from the Scene system, not the
> compositor. Anyways, given the review comments, it seems that this will be
> explored differently, so abstain.
And that's ok, but until we actually have that alternative -whatever it is - it doesn't make sense to remove functionality until then.
- 1569. By Daniel van Vugt
-
Merge latest development-branch
- 1570. By Daniel van Vugt
-
Merge latest development-branch
- 1571. By Daniel van Vugt
-
Merge latest development-branch
- 1572. By Daniel van Vugt
-
Merge latest development-branch
- 1573. By Daniel van Vugt
-
Merge latest development-branch
Daniel van Vugt (vanvugt) wrote : | # |
I'm not entirely sure now how much benefit occlusion detection could provide in the non-blocking world. You lose the benefit of limiting client CPU/GPU usage because you have to force unblocking of clients under the new model.
There's only one benefit remaining. That is to reduce the number of renderables that get thrown at the renderer. But OpenGL has always, by design, optimized out offscreen textures and geometry anyway. So that just gives you one obscure uncommon benefit: A small renderable hidden behind a larger one does not get its texture uploaded on that frame. However this benefit only applies to software surfaces where there is an actual "upload", and is irrelevant if the foreground is fullscreen because that's already optimized by bypass. The benefit of occlusion detection in the non-blocking world seems negligible.
Daniel van Vugt (vanvugt) wrote : | # |
Also, when you throw decorations into the mix the current occlusion detection is wrong and buggy (like bug 1299977). With decorations you need even more complicated occlusion detection such that you only test if the client area of the foreground window fully occludes the decorated window frame of the background window.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1573
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alberto Aguirre (albaguirre) wrote : | # |
A small renderable hidden behind a larger one
> does not get its texture uploaded on that frame. However this benefit only
> applies to software surfaces where there is an actual "upload", and is
> irrelevant if the foreground is fullscreen because that's already optimized by
> bypass. The benefit of occlusion detection in the non-blocking world seems
> negligible.
A "small" renderable could be simply one pixel less in width and height than the one that occludes it, which could be 2559x1599 in a nexus 10 for example.
It used to be that qualcomm chipsets were all direct rendering implementations, so it WOULD read that texture since we are drawing back to front. Now it seems it can switch between direct and deferred rendering so maybe it's smart enough not to do that anymore.
The Nexus 10 Mali does tile-based deferred rendering (as does the PowerVR stuff) so I suspect it's not a huge impact there either.
You could also get the additional hit of programming the GPU MMU - some architectures will lazily do that (i.e. they will not "upload" program the mmu until a draw command references it).
But we are both speculating - I would like to see some evidence that the occlusion optimization is negligible.
- 1574. By Daniel van Vugt
-
Merge latest development-branch and fix conflicts
Daniel van Vugt (vanvugt) wrote : | # |
I wrote the texture cache logic in GLRenderer, so I know it behaves the same on any platform and that's not speculation.
The remaining point is whether uploading unused vertices is negligible for the number of surfaces on a desktop. I would argue after a while working on Compiz I got a good idea that yes, it is negligible. So that's a strongly educated guess rather than speculation.
Daniel van Vugt (vanvugt) wrote : | # |
Hmm, actually the texture cache isn't relevant because it would be invalidated on frames that are important here. Yes I'm speculating then because the performance hit is now GPU-specific.
Another speculation is that performing occlusion tests at all is fast enough to justify the effort. That's an assumption made in Mir right now. But I know from previous work it doesn't always hold true.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1574
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1575. By Daniel van Vugt
-
Merge latest development-branch
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1575
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1576. By Daniel van Vugt
-
Merge latest development-branch
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1576
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1577. By Daniel van Vugt
-
Merge latest development-branch and fix conflicts
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1577
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
- 1577. By Daniel van Vugt
-
Merge latest development-branch and fix conflicts
- 1576. By Daniel van Vugt
-
Merge latest development-branch
- 1575. By Daniel van Vugt
-
Merge latest development-branch
- 1574. By Daniel van Vugt
-
Merge latest development-branch and fix conflicts
- 1573. By Daniel van Vugt
-
Merge latest development-branch
- 1572. By Daniel van Vugt
-
Merge latest development-branch
- 1571. By Daniel van Vugt
-
Merge latest development-branch
- 1570. By Daniel van Vugt
-
Merge latest development-branch
- 1569. By Daniel van Vugt
-
Merge latest development-branch
- 1568. By Daniel van Vugt
-
First attempt at removing occlusion detection
Preview Diff
1 | === modified file 'src/server/compositor/CMakeLists.txt' |
2 | --- src/server/compositor/CMakeLists.txt 2014-04-27 21:11:15 +0000 |
3 | +++ src/server/compositor/CMakeLists.txt 2014-05-06 03:00:37 +0000 |
4 | @@ -10,7 +10,6 @@ |
5 | gl_renderer_factory.cpp |
6 | multi_threaded_compositor.cpp |
7 | bypass.cpp |
8 | - occlusion.cpp |
9 | default_configuration.cpp |
10 | screencast_display_buffer.cpp |
11 | compositing_screencast.cpp |
12 | |
13 | === modified file 'src/server/compositor/default_display_buffer_compositor.cpp' |
14 | --- src/server/compositor/default_display_buffer_compositor.cpp 2014-05-05 05:43:02 +0000 |
15 | +++ src/server/compositor/default_display_buffer_compositor.cpp 2014-05-06 03:00:37 +0000 |
16 | @@ -26,7 +26,6 @@ |
17 | #include "mir/graphics/buffer.h" |
18 | #include "mir/compositor/buffer_stream.h" |
19 | #include "bypass.h" |
20 | -#include "occlusion.h" |
21 | #include <mutex> |
22 | #include <cstdlib> |
23 | #include <algorithm> |
24 | @@ -55,7 +54,6 @@ |
25 | |
26 | auto const& view_area = display_buffer.view_area(); |
27 | auto renderable_list = scene->renderable_list_for(this); |
28 | - mc::filter_occlusions_from(renderable_list, view_area); |
29 | |
30 | //TODO: the DisplayBufferCompositor should not have to figure out if it has to force |
31 | // a subsequent compositon. The MultiThreadedCompositor should be smart enough to |
32 | |
33 | === removed file 'src/server/compositor/occlusion.cpp' |
34 | --- src/server/compositor/occlusion.cpp 2014-04-17 01:34:35 +0000 |
35 | +++ src/server/compositor/occlusion.cpp 1970-01-01 00:00:00 +0000 |
36 | @@ -1,78 +0,0 @@ |
37 | -/* |
38 | - * Copyright © 2013 Canonical Ltd. |
39 | - * |
40 | - * This program is free software: you can redistribute it and/or modify it |
41 | - * under the terms of the GNU General Public License version 3, |
42 | - * as published by the Free Software Foundation. |
43 | - * |
44 | - * This program is distributed in the hope that it will be useful, |
45 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
46 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
47 | - * GNU General Public License for more details. |
48 | - * |
49 | - * You should have received a copy of the GNU General Public License |
50 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
51 | - * |
52 | - * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com> |
53 | - */ |
54 | - |
55 | -#include "mir/geometry/rectangle.h" |
56 | -#include "mir/graphics/renderable.h" |
57 | -#include "occlusion.h" |
58 | - |
59 | -using namespace mir::geometry; |
60 | -using namespace mir::graphics; |
61 | - |
62 | -namespace |
63 | -{ |
64 | -bool renderable_is_occluded( |
65 | - Renderable const& renderable, |
66 | - Rectangle const& area, |
67 | - std::vector<Rectangle>& coverage) |
68 | -{ |
69 | - static const glm::mat4 identity; |
70 | - if (renderable.transformation() != identity) |
71 | - return false; // Weirdly transformed. Assume never occluded. |
72 | - |
73 | - //TODO: remove this check, why are we getting a non visible renderable |
74 | - // in the list of surfaces? |
75 | - // This will check the surface is not hidden and has been posted. |
76 | - if (!renderable.visible()) |
77 | - return true; //invisible; definitely occluded. |
78 | - |
79 | - // Not weirdly transformed but also not on this monitor? Don't care... |
80 | - if (!area.overlaps(renderable.screen_position())) |
81 | - return true; // Not on the display; definitely occluded. |
82 | - |
83 | - bool occluded = false; |
84 | - Rectangle const& window = renderable.screen_position(); |
85 | - for (const auto &r : coverage) |
86 | - { |
87 | - if (r.contains(window)) |
88 | - { |
89 | - occluded = true; |
90 | - break; |
91 | - } |
92 | - } |
93 | - |
94 | - if (!occluded && renderable.alpha() == 1.0f && !renderable.shaped()) |
95 | - coverage.push_back(window); |
96 | - |
97 | - return occluded; |
98 | -} |
99 | -} |
100 | - |
101 | -void mir::compositor::filter_occlusions_from( |
102 | - RenderableList& list, |
103 | - Rectangle const& area) |
104 | -{ |
105 | - std::vector<Rectangle> coverage; |
106 | - auto it = list.rbegin(); |
107 | - while (it != list.rend()) |
108 | - { |
109 | - if (renderable_is_occluded(**it, area, coverage)) |
110 | - list.erase(std::prev(it.base())); |
111 | - else |
112 | - it++; |
113 | - } |
114 | -} |
115 | |
116 | === removed file 'src/server/compositor/occlusion.h' |
117 | --- src/server/compositor/occlusion.h 2014-03-26 16:59:32 +0000 |
118 | +++ src/server/compositor/occlusion.h 1970-01-01 00:00:00 +0000 |
119 | @@ -1,37 +0,0 @@ |
120 | -/* |
121 | - * Copyright © 2013 Canonical Ltd. |
122 | - * |
123 | - * This program is free software: you can redistribute it and/or modify it |
124 | - * under the terms of the GNU General Public License version 3, |
125 | - * as published by the Free Software Foundation. |
126 | - * |
127 | - * This program is distributed in the hope that it will be useful, |
128 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
129 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
130 | - * GNU General Public License for more details. |
131 | - * |
132 | - * You should have received a copy of the GNU General Public License |
133 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
134 | - * |
135 | - * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com> |
136 | - */ |
137 | - |
138 | -#ifndef MIR_COMPOSITOR_OCCLUSION_H_ |
139 | -#define MIR_COMPOSITOR_OCCLUSION_H_ |
140 | - |
141 | -#include "mir/graphics/renderable.h" |
142 | -#include "mir/compositor/scene.h" |
143 | -#include <vector> |
144 | -#include <set> |
145 | - |
146 | -namespace mir |
147 | -{ |
148 | -namespace compositor |
149 | -{ |
150 | - |
151 | -void filter_occlusions_from(graphics::RenderableList& list, geometry::Rectangle const& area); |
152 | - |
153 | -} // namespace compositor |
154 | -} // namespace mir |
155 | - |
156 | -#endif // MIR_COMPOSITOR_OCCLUSION_H_ |
157 | |
158 | === modified file 'tests/integration-tests/test_surface_first_frame_sync.cpp' |
159 | --- tests/integration-tests/test_surface_first_frame_sync.cpp 2014-05-05 05:43:02 +0000 |
160 | +++ tests/integration-tests/test_surface_first_frame_sync.cpp 2014-05-06 03:00:37 +0000 |
161 | @@ -105,8 +105,8 @@ |
162 | { |
163 | for (auto const& r : renderables) |
164 | { |
165 | - (void)r; |
166 | - while (write(render_operations_fd, "a", 1) != 1) continue; |
167 | + if (r->visible()) |
168 | + while (write(render_operations_fd, "a", 1) != 1) continue; |
169 | } |
170 | } |
171 | |
172 | |
173 | === modified file 'tests/unit-tests/compositor/CMakeLists.txt' |
174 | --- tests/unit-tests/compositor/CMakeLists.txt 2014-04-21 15:56:41 +0000 |
175 | +++ tests/unit-tests/compositor/CMakeLists.txt 2014-05-06 03:00:37 +0000 |
176 | @@ -6,7 +6,6 @@ |
177 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_queue.cpp |
178 | ${CMAKE_CURRENT_SOURCE_DIR}/test_gl_renderer.cpp |
179 | ${CMAKE_CURRENT_SOURCE_DIR}/test_bypass.cpp |
180 | - ${CMAKE_CURRENT_SOURCE_DIR}/test_occlusion.cpp |
181 | ${CMAKE_CURRENT_SOURCE_DIR}/test_screencast_display_buffer.cpp |
182 | ${CMAKE_CURRENT_SOURCE_DIR}/test_compositing_screencast.cpp |
183 | ) |
184 | |
185 | === modified file 'tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp' |
186 | --- tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2014-05-05 05:43:02 +0000 |
187 | +++ tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2014-05-06 03:00:37 +0000 |
188 | @@ -128,66 +128,6 @@ |
189 | compositor.composite(); |
190 | } |
191 | |
192 | -TEST_F(DefaultDisplayBufferCompositor, skips_scene_that_should_not_be_rendered) |
193 | -{ |
194 | - using namespace testing; |
195 | - |
196 | - mtd::StubDisplayBuffer display_buffer{geom::Rectangle{{0,0},{14,14}}}; |
197 | - auto mock_renderable1 = std::make_shared<NiceMock<mtd::MockRenderable>>(); |
198 | - auto mock_renderable2 = std::make_shared<NiceMock<mtd::MockRenderable>>(); |
199 | - auto mock_renderable3 = std::make_shared<NiceMock<mtd::MockRenderable>>(); |
200 | - |
201 | - glm::mat4 simple; |
202 | - EXPECT_CALL(*mock_renderable1, transformation()) |
203 | - .WillOnce(Return(simple)); |
204 | - EXPECT_CALL(*mock_renderable2, transformation()) |
205 | - .WillOnce(Return(simple)); |
206 | - EXPECT_CALL(*mock_renderable3, transformation()) |
207 | - .WillOnce(Return(simple)); |
208 | - |
209 | - EXPECT_CALL(*mock_renderable1, visible()) |
210 | - .WillRepeatedly(Return(true)); |
211 | - EXPECT_CALL(*mock_renderable2, visible()) |
212 | - .WillRepeatedly(Return(false)); |
213 | - EXPECT_CALL(*mock_renderable3, visible()) |
214 | - .WillRepeatedly(Return(true)); |
215 | - |
216 | - EXPECT_CALL(*mock_renderable1, alpha()) |
217 | - .WillOnce(Return(1.0f)); |
218 | - EXPECT_CALL(*mock_renderable3, alpha()) |
219 | - .WillOnce(Return(1.0f)); |
220 | - |
221 | - EXPECT_CALL(*mock_renderable1, shaped()) |
222 | - .WillOnce(Return(false)); |
223 | - EXPECT_CALL(*mock_renderable3, shaped()) |
224 | - .WillOnce(Return(false)); |
225 | - |
226 | - EXPECT_CALL(*mock_renderable1, screen_position()) |
227 | - .WillRepeatedly(Return(geom::Rectangle{{1,2}, {3,4}})); |
228 | - EXPECT_CALL(*mock_renderable2, screen_position()) |
229 | - .WillRepeatedly(Return(geom::Rectangle{{1,2}, {3,4}})); |
230 | - EXPECT_CALL(*mock_renderable3, screen_position()) |
231 | - .WillRepeatedly(Return(geom::Rectangle{{5,6}, {7,8}})); |
232 | - |
233 | - mg::RenderableList list{ |
234 | - mock_renderable1, |
235 | - mock_renderable2, |
236 | - mock_renderable3 |
237 | - }; |
238 | - FakeScene scene(list); |
239 | - |
240 | - mg::RenderableList const visible{mock_renderable1, mock_renderable3}; |
241 | - EXPECT_CALL(mock_renderer, render(visible)) |
242 | - .Times(1); |
243 | - |
244 | - mc::DefaultDisplayBufferCompositor compositor( |
245 | - display_buffer, |
246 | - mt::fake_shared(scene), |
247 | - mt::fake_shared(mock_renderer), |
248 | - mr::null_compositor_report()); |
249 | - compositor.composite(); |
250 | -} |
251 | - |
252 | TEST_F(DefaultDisplayBufferCompositor, bypass_skips_composition) |
253 | { |
254 | using namespace testing; |
255 | @@ -304,8 +244,6 @@ |
256 | }; |
257 | FakeScene scene(list); |
258 | |
259 | - mg::RenderableList const visible{fullscreen}; |
260 | - |
261 | EXPECT_CALL(display_buffer, view_area()) |
262 | .WillRepeatedly(Return(screen)); |
263 | EXPECT_CALL(display_buffer, make_current()) |
264 | @@ -316,7 +254,7 @@ |
265 | .Times(1); |
266 | EXPECT_CALL(display_buffer, can_bypass()) |
267 | .WillRepeatedly(Return(false)); |
268 | - EXPECT_CALL(mock_renderer, render(visible)) |
269 | + EXPECT_CALL(mock_renderer, render(list)) |
270 | .Times(1); |
271 | |
272 | mc::DefaultDisplayBufferCompositor compositor( |
273 | @@ -348,8 +286,7 @@ |
274 | }; |
275 | FakeScene scene(list); |
276 | |
277 | - mg::RenderableList const visible{fullscreen}; |
278 | - EXPECT_CALL(mock_renderer, render(visible)) |
279 | + EXPECT_CALL(mock_renderer, render(list)) |
280 | .Times(1); |
281 | |
282 | auto nonbypassable = std::make_shared<mtd::MockBuffer>(); |
283 | @@ -437,7 +374,7 @@ |
284 | fullscreen->set_buffer({}); // Avoid GMock complaining about false leaks |
285 | } |
286 | |
287 | -TEST_F(DefaultDisplayBufferCompositor, occluded_surfaces_are_not_rendered) |
288 | +TEST_F(DefaultDisplayBufferCompositor, occluded_surfaces_are_rendered_too) |
289 | { |
290 | using namespace testing; |
291 | EXPECT_CALL(display_buffer, view_area()) |
292 | @@ -462,12 +399,11 @@ |
293 | }); |
294 | FakeScene scene(list); |
295 | |
296 | - mg::RenderableList const visible{window0, window3}; |
297 | |
298 | Sequence seq; |
299 | EXPECT_CALL(display_buffer, make_current()) |
300 | .InSequence(seq); |
301 | - EXPECT_CALL(mock_renderer, render(visible)) |
302 | + EXPECT_CALL(mock_renderer, render(list)) |
303 | .InSequence(seq); |
304 | EXPECT_CALL(display_buffer, post_update()) |
305 | .InSequence(seq); |
306 | |
307 | === removed file 'tests/unit-tests/compositor/test_occlusion.cpp' |
308 | --- tests/unit-tests/compositor/test_occlusion.cpp 2014-04-02 03:10:06 +0000 |
309 | +++ tests/unit-tests/compositor/test_occlusion.cpp 1970-01-01 00:00:00 +0000 |
310 | @@ -1,202 +0,0 @@ |
311 | -/* |
312 | - * Copyright © 2013 Canonical Ltd. |
313 | - * |
314 | - * This program is free software: you can redistribute it and/or modify |
315 | - * it under the terms of the GNU General Public License version 3 as |
316 | - * published by the Free Software Foundation. |
317 | - * |
318 | - * This program is distributed in the hope that it will be useful, |
319 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
320 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
321 | - * GNU General Public License for more details. |
322 | - * |
323 | - * You should have received a copy of the GNU General Public License |
324 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
325 | - * |
326 | - * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com> |
327 | - */ |
328 | - |
329 | -#include "mir/geometry/rectangle.h" |
330 | -#include "src/server/compositor/occlusion.h" |
331 | -#include "mir_test_doubles/fake_renderable.h" |
332 | - |
333 | -#include <gtest/gtest.h> |
334 | -#include <memory> |
335 | - |
336 | -using namespace testing; |
337 | -using namespace mir::geometry; |
338 | -using namespace mir::compositor; |
339 | -namespace mg = mir::graphics; |
340 | -namespace mtd = mir::test::doubles; |
341 | - |
342 | -struct OcclusionFilterTest : public Test |
343 | -{ |
344 | - OcclusionFilterTest() |
345 | - { |
346 | - monitor_rect.top_left = {0, 0}; |
347 | - monitor_rect.size = {1920, 1200}; |
348 | - } |
349 | - |
350 | - Rectangle monitor_rect; |
351 | -}; |
352 | - |
353 | -TEST_F(OcclusionFilterTest, single_window_not_occluded) |
354 | -{ |
355 | - auto window = std::make_shared<mtd::FakeRenderable>(12, 34, 56, 78); |
356 | - mg::RenderableList list{window}; |
357 | - |
358 | - filter_occlusions_from(list, monitor_rect); |
359 | - ASSERT_EQ(1u, list.size()); |
360 | - EXPECT_EQ(window, list.front()); |
361 | -} |
362 | - |
363 | -TEST_F(OcclusionFilterTest, partially_offscreen_still_visible) |
364 | -{ // Regression test for LP: #1301115 |
365 | - auto left = std::make_shared<mtd::FakeRenderable>(-10, 10, 100, 100); |
366 | - auto right = std::make_shared<mtd::FakeRenderable>(1900, 10, 100, 100); |
367 | - auto top = std::make_shared<mtd::FakeRenderable>(500, -1, 100, 100); |
368 | - auto bottom = std::make_shared<mtd::FakeRenderable>(200, 1000, 100, 1000); |
369 | - mg::RenderableList list{left, right, top, bottom}; |
370 | - |
371 | - filter_occlusions_from(list, monitor_rect); |
372 | - EXPECT_EQ(4u, list.size()); |
373 | -} |
374 | - |
375 | -TEST_F(OcclusionFilterTest, smaller_window_occluded) |
376 | -{ |
377 | - auto top = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10); |
378 | - auto bottom = std::make_shared<mtd::FakeRenderable>(12, 12, 5, 5); |
379 | - mg::RenderableList list{bottom, top}; |
380 | - |
381 | - filter_occlusions_from(list, monitor_rect); |
382 | - |
383 | - ASSERT_EQ(1u, list.size()); |
384 | - EXPECT_EQ(top, list.front()); |
385 | -} |
386 | - |
387 | -TEST_F(OcclusionFilterTest, translucent_window_occludes_nothing) |
388 | -{ |
389 | - auto top = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10, 0.5f); |
390 | - auto bottom = std::make_shared<mtd::FakeRenderable>(12, 12, 5, 5, 1.0f); |
391 | - mg::RenderableList list{bottom, top}; |
392 | - |
393 | - filter_occlusions_from(list, monitor_rect); |
394 | - |
395 | - ASSERT_EQ(2u, list.size()); |
396 | - EXPECT_EQ(bottom, list.front()); |
397 | - EXPECT_EQ(top, list.back()); |
398 | -} |
399 | - |
400 | -TEST_F(OcclusionFilterTest, hidden_window_is_self_occluded) |
401 | -{ |
402 | - auto window = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10, 1.0f, true, false); |
403 | - mg::RenderableList list{window}; |
404 | - |
405 | - filter_occlusions_from(list, monitor_rect); |
406 | - |
407 | - EXPECT_EQ(0u, list.size()); |
408 | -} |
409 | - |
410 | -TEST_F(OcclusionFilterTest, hidden_window_occludes_nothing) |
411 | -{ |
412 | - auto top = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10, 1.0f, true, false); |
413 | - auto bottom = std::make_shared<mtd::FakeRenderable>(12, 12, 5, 5); |
414 | - mg::RenderableList list{bottom, top}; |
415 | - |
416 | - filter_occlusions_from(list, monitor_rect); |
417 | - |
418 | - ASSERT_EQ(1u, list.size()); |
419 | - EXPECT_EQ(bottom, list.front()); |
420 | -} |
421 | - |
422 | -TEST_F(OcclusionFilterTest, shaped_window_occludes_nothing) |
423 | -{ |
424 | - auto top = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10, 1.0f, false, true); |
425 | - auto bottom = std::make_shared<mtd::FakeRenderable>(12, 12, 5, 5); |
426 | - mg::RenderableList list{bottom, top}; |
427 | - |
428 | - filter_occlusions_from(list, monitor_rect); |
429 | - |
430 | - ASSERT_EQ(2u, list.size()); |
431 | - EXPECT_EQ(bottom, list.front()); |
432 | - EXPECT_EQ(top, list.back()); |
433 | -} |
434 | - |
435 | -TEST_F(OcclusionFilterTest, identical_window_occluded) |
436 | -{ |
437 | - auto top = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10); |
438 | - auto bottom = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10); |
439 | - mg::RenderableList list{bottom, top}; |
440 | - |
441 | - filter_occlusions_from(list, monitor_rect); |
442 | - |
443 | - ASSERT_EQ(1u, list.size()); |
444 | - EXPECT_EQ(top, list.front()); |
445 | -} |
446 | - |
447 | -TEST_F(OcclusionFilterTest, larger_window_never_occluded) |
448 | -{ |
449 | - auto top = std::make_shared<mtd::FakeRenderable>(10, 10, 10, 10); |
450 | - auto bottom = std::make_shared<mtd::FakeRenderable>(9, 9, 12, 12); |
451 | - mg::RenderableList list{bottom, top}; |
452 | - |
453 | - filter_occlusions_from(list, monitor_rect); |
454 | - |
455 | - ASSERT_EQ(2u, list.size()); |
456 | - EXPECT_EQ(bottom, list.front()); |
457 | - EXPECT_EQ(top, list.back()); |
458 | -} |
459 | - |
460 | -TEST_F(OcclusionFilterTest, cascaded_windows_never_occluded) |
461 | -{ |
462 | - mg::RenderableList list; |
463 | - unsigned int const num_windows{10u}; |
464 | - for (auto x = 0u; x < num_windows; x++) |
465 | - list.push_back(std::make_shared<mtd::FakeRenderable>(x, x, 200, 100)); |
466 | - |
467 | - filter_occlusions_from(list, monitor_rect); |
468 | - EXPECT_EQ(num_windows, list.size()); |
469 | -} |
470 | - |
471 | -TEST_F(OcclusionFilterTest, some_occluded_and_some_not) |
472 | -{ |
473 | - auto window0 = std::make_shared<mtd::FakeRenderable>(10, 20, 400, 300); |
474 | - auto window1 = std::make_shared<mtd::FakeRenderable>(10, 20, 5, 5); |
475 | - auto window2 = std::make_shared<mtd::FakeRenderable>(100, 100, 20, 20); |
476 | - auto window3 = std::make_shared<mtd::FakeRenderable>(200, 200, 50, 50); |
477 | - auto window4 = std::make_shared<mtd::FakeRenderable>(500, 600, 34, 56); |
478 | - auto window5 = std::make_shared<mtd::FakeRenderable>(200, 200, 1000, 1000); |
479 | - mg::RenderableList list{ |
480 | - window5, //not occluded |
481 | - window4, //not occluded |
482 | - window3, //occluded |
483 | - window2, //occluded |
484 | - window1, //occluded |
485 | - window0 //not occluded |
486 | - }; |
487 | - |
488 | - filter_occlusions_from(list, monitor_rect); |
489 | - |
490 | - auto expected_size = 3u; |
491 | - ASSERT_EQ(expected_size, list.size()); |
492 | - auto it = list.begin(); |
493 | - for(auto count = 0u; count < expected_size; count++) |
494 | - { |
495 | - switch (count) |
496 | - { |
497 | - case 0u: |
498 | - EXPECT_EQ(window5, *it); |
499 | - break; |
500 | - case 1u: |
501 | - EXPECT_EQ(window4, *it); |
502 | - break; |
503 | - case 2u: |
504 | - EXPECT_EQ(window0, *it); |
505 | - break; |
506 | - default: |
507 | - FAIL(); |
508 | - break; |
509 | - } |
510 | - it++; |
511 | - } |
512 | -} |
I thought I needed this as a prerequisite to another fix I have in progress but now am not sure. Still, it's worth discussing.