Mir

Merge lp:~kdub/mir/fix-1274189 into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 1367
Proposed branch: lp:~kdub/mir/fix-1274189
Merge into: lp:mir
Diff against target: 261 lines (+46/-20)
6 files modified
include/test/mir_test_doubles/mock_hwc_composer_device_1.h (+9/-1)
src/platform/graphics/android/hwc_device.cpp (+4/-7)
src/platform/graphics/android/hwc_device.h (+2/-3)
src/platform/graphics/android/resource_factory.cpp (+3/-1)
tests/unit-tests/graphics/android/test_hwc_common_device.cpp (+3/-1)
tests/unit-tests/graphics/android/test_hwc_device.cpp (+25/-7)
To merge this branch: bzr merge lp:~kdub/mir/fix-1274189
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
Gerry Boland (community) functional Approve
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+204314@code.launchpad.net

Commit message

graphics: android: remove wait on retireFenceFd. On some platforms (specifically the 4.4-based flo and grouper), this wait was causing us to miss vsync.

fixes lp: #1274189

Description of the change

graphics: android: remove wait on retireFenceFd. On some platforms (specifically the 4.4-based flo and grouper), this wait was causing us to miss vsync.

top level summary:
retireFenceFd as described (line 296 https://android.googlesource.com/platform/hardware/libhardware/+/android-4.4.2_r1/include/hardware/hwcomposer.h ) says that the fence will signal when the composition has been replaced on screen by subsequent set. It seems that waiting for the last post to leave the screen is not necessarily the same thing as the just-called commit to get to the screen, resulting in missing vsync. hwc api guarantees that the post will get to the screen without artifacts, and we use fences more extensively now to guarantee no tears for the gpu or the fb.

Lastly, surfaceflinger doesn't wait for this fence for the physical display, rather it seems used to coordinate with the 'virtual' display (which mir doesn't implement yet). We still have the responsibility to close the fd, which we do in this MP.

historical note:
I think this code was put in when we weren't implementing fences correctly in the system, circa october 2013-ish. It didn't manifest itself as a problem until now because none of the drivers we were commonly running on would either 1) not wait here at all because the driver didn't set it, or 2) just wait here as opposed to waiting on the subsequent gpu render of the framebuffer.

fixes lp: #1274189

test procedure:
Since this affects display, was tested with the full stack manually to check for tears and the frame times were logged.

tested (no tears, ~16 ms frame time):
flo (android 4.4, hwc 1.2)
manta (android 4.4, hwc 1.1)
mako (android 4.4, hwc 1.2)
grouper (android 4.4, hwc 1.1)
mako (android 4.2, hwc 1.1)
manta (android 4.2, hwc 1.1)

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

Seems to work for me. At least as well as before.

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

Big improvement on Nexus7(2013)/Flo

review: Approve (functional)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Flo is really fast now, +1.

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

Code looks reasonable and there's enough approvals. Top approving.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/test/mir_test_doubles/mock_hwc_composer_device_1.h'
2--- include/test/mir_test_doubles/mock_hwc_composer_device_1.h 2014-01-23 17:26:51 +0000
3+++ include/test/mir_test_doubles/mock_hwc_composer_device_1.h 2014-01-31 18:37:40 +0000
4@@ -76,6 +76,11 @@
5 fb_fence = fence;
6 }
7
8+ void hwc_set_retire_fence(int fence)
9+ {
10+ retire_fence = fence;
11+ }
12+
13 int save_last_prepare_arguments(struct hwc_composer_device_1 *, size_t size, hwc_display_contents_1_t** displays)
14 {
15 if ((size == 0) || (!displays))
16@@ -122,12 +127,14 @@
17 set_layerlist.back().visibleRegionScreen = {0, nullptr};
18 }
19
20+ save_args(&display0_set_content, displays);
21+
22 if (displays[0]->numHwLayers >= 2)
23 {
24 displays[0]->hwLayers[1].releaseFenceFd = fb_fence;
25+ displays[0]->retireFenceFd = retire_fence;
26 }
27
28- save_args(&display0_set_content, displays);
29 default:
30 break;
31 }
32@@ -186,6 +193,7 @@
33 std::vector<hwc_layer_1> prepare_layerlist;
34 hwc_display_contents_1_t display0_prepare_content;
35 int fb_fence;
36+ int retire_fence;
37 };
38
39 }
40
41=== modified file 'src/platform/graphics/android/hwc_device.cpp'
42--- src/platform/graphics/android/hwc_device.cpp 2014-01-23 18:01:19 +0000
43+++ src/platform/graphics/android/hwc_device.cpp 2014-01-31 18:37:40 +0000
44@@ -35,10 +35,11 @@
45 namespace geom = mir::geometry;
46
47 mga::HwcDevice::HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
48- std::shared_ptr<HWCVsyncCoordinator> const& coordinator)
49+ std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
50+ std::shared_ptr<SyncFileOps> const& sync_ops)
51 : HWCCommonDevice(hwc_device, coordinator),
52 layer_list({mga::ForceGLLayer{}, mga::FramebufferLayer{}}),
53- sync_ops(std::make_shared<mga::RealSyncFileOps>())
54+ sync_ops(sync_ops)
55 {
56 }
57
58@@ -79,12 +80,8 @@
59 BOOST_THROW_EXCEPTION(std::runtime_error("error during hwc set()"));
60 }
61
62- if (last_display_fence)
63- last_display_fence->wait();
64+ mga::SyncFence retire_fence(sync_ops, displays[HWC_DISPLAY_PRIMARY]->retireFenceFd);
65
66 int framebuffer_fence = layer_list.framebuffer_fence();
67 native_buffer->update_fence(framebuffer_fence);
68-
69- last_display_fence = std::make_shared<mga::SyncFence>(
70- sync_ops, displays[HWC_DISPLAY_PRIMARY]->retireFenceFd);
71 }
72
73=== modified file 'src/platform/graphics/android/hwc_device.h'
74--- src/platform/graphics/android/hwc_device.h 2014-01-23 18:01:19 +0000
75+++ src/platform/graphics/android/hwc_device.h 2014-01-31 18:37:40 +0000
76@@ -34,13 +34,13 @@
77 {
78 class HWCVsyncCoordinator;
79 class SyncFileOps;
80-class SyncFence;
81
82 class HwcDevice : public HWCCommonDevice
83 {
84 public:
85 HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
86- std::shared_ptr<HWCVsyncCoordinator> const& coordinator);
87+ std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
88+ std::shared_ptr<SyncFileOps> const& sync_ops);
89
90 void prepare_gl();
91 void prepare_gl_and_overlays(std::list<std::shared_ptr<Renderable>> const& list);
92@@ -50,7 +50,6 @@
93 private:
94 LayerList layer_list;
95
96- std::shared_ptr<SyncFence> last_display_fence;
97 std::shared_ptr<SyncFileOps> const sync_ops;
98 unsigned int primary_display_config;
99 MirPixelFormat fb_format;
100
101=== modified file 'src/platform/graphics/android/resource_factory.cpp'
102--- src/platform/graphics/android/resource_factory.cpp 2014-01-21 18:09:35 +0000
103+++ src/platform/graphics/android/resource_factory.cpp 2014-01-31 18:37:40 +0000
104@@ -18,6 +18,7 @@
105 */
106
107 #include "mir/graphics/android/mir_native_window.h"
108+#include "mir/graphics/android/sync_fence.h"
109 #include "buffer.h"
110 #include "resource_factory.h"
111 #include "fb_device.h"
112@@ -91,7 +92,8 @@
113 std::shared_ptr<hwc_composer_device_1> const& hwc_native_device) const
114 {
115 auto syncer = std::make_shared<mga::HWCVsync>();
116- return std::make_shared<mga::HwcDevice>(hwc_native_device, syncer);
117+ auto file_ops = std::make_shared<mga::RealSyncFileOps>();
118+ return std::make_shared<mga::HwcDevice>(hwc_native_device, syncer, file_ops);
119 }
120
121 std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(
122
123=== modified file 'tests/unit-tests/graphics/android/test_hwc_common_device.cpp'
124--- tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-01-21 18:09:35 +0000
125+++ tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-01-31 18:37:40 +0000
126@@ -16,6 +16,7 @@
127 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
128 */
129
130+#include "mir/graphics/android/sync_fence.h"
131 #include "src/platform/graphics/android/hwc_fb_device.h"
132 #include "src/platform/graphics/android/hwc_device.h"
133 #include "src/platform/graphics/android/hwc_layerlist.h"
134@@ -58,7 +59,8 @@
135 std::shared_ptr<framebuffer_device_t> const&,
136 std::shared_ptr<mga::HWCVsyncCoordinator> const& coordinator)
137 {
138- return std::make_shared<mga::HwcDevice>(hwc_device, coordinator);
139+ auto file_ops = std::make_shared<mga::RealSyncFileOps>();
140+ return std::make_shared<mga::HwcDevice>(hwc_device, coordinator, file_ops);
141 }
142
143 template<typename T>
144
145=== modified file 'tests/unit-tests/graphics/android/test_hwc_device.cpp'
146--- tests/unit-tests/graphics/android/test_hwc_device.cpp 2014-01-23 17:26:51 +0000
147+++ tests/unit-tests/graphics/android/test_hwc_device.cpp 2014-01-31 18:37:40 +0000
148@@ -16,6 +16,7 @@
149 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
150 */
151
152+#include "mir/graphics/android/sync_fence.h"
153 #include "src/platform/graphics/android/framebuffer_bundle.h"
154 #include "src/platform/graphics/android/hwc_device.h"
155 #include "src/platform/graphics/android/hwc_layerlist.h"
156@@ -35,6 +36,16 @@
157 namespace mtd=mir::test::doubles;
158 namespace geom=mir::geometry;
159
160+namespace
161+{
162+struct MockFileOps : public mga::SyncFileOps
163+{
164+ MOCK_METHOD3(ioctl, int(int,int,void*));
165+ MOCK_METHOD1(dup, int(int));
166+ MOCK_METHOD1(close, int(int));
167+};
168+}
169+
170 class HwcDevice : public ::testing::Test
171 {
172 protected:
173@@ -48,10 +59,13 @@
174 mock_buffer = std::make_shared<testing::NiceMock<mtd::MockBuffer>>();
175 mock_device = std::make_shared<testing::NiceMock<mtd::MockHWCComposerDevice1>>();
176 mock_vsync = std::make_shared<testing::NiceMock<mtd::MockVsyncCoordinator>>();
177+ mock_file_ops = std::make_shared<MockFileOps>();
178
179 ON_CALL(*mock_buffer, native_buffer_handle())
180 .WillByDefault(Return(mock_native_buffer));
181 }
182+
183+ std::shared_ptr<MockFileOps> mock_file_ops;
184 std::shared_ptr<mtd::MockVsyncCoordinator> mock_vsync;
185 std::shared_ptr<mtd::MockHWCComposerDevice1> mock_device;
186 std::shared_ptr<mtd::MockAndroidNativeBuffer> mock_native_buffer;
187@@ -69,7 +83,7 @@
188 EXPECT_CALL(*mock_device, set_interface(mock_device.get(),_,_))
189 .Times(1);
190
191- mga::HwcDevice device(mock_device, mock_vsync);
192+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
193 device.prepare_gl();
194 device.post(*mock_buffer);
195
196@@ -90,7 +104,7 @@
197 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))
198 .Times(1);
199
200- mga::HwcDevice device(mock_device, mock_vsync);
201+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
202 device.prepare_gl();
203 EXPECT_EQ(2, mock_device->display0_prepare_content.numHwLayers);
204 EXPECT_EQ(-1, mock_device->display0_prepare_content.retireFenceFd);
205@@ -102,7 +116,7 @@
206 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))
207 .Times(1);
208
209- mga::HwcDevice device(mock_device, mock_vsync);
210+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
211 std::list<std::shared_ptr<mg::Renderable>> renderlist;
212 device.prepare_gl_and_overlays(renderlist);
213
214@@ -114,7 +128,7 @@
215 {
216 EXPECT_CALL(mock_egl, eglSwapBuffers(dpy,surf))
217 .Times(1);
218- mga::HwcDevice device(mock_device, mock_vsync);
219+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
220 device.gpu_render(dpy, surf);
221 }
222
223@@ -125,7 +139,7 @@
224 .Times(1)
225 .WillOnce(Return(EGL_FALSE));
226
227- mga::HwcDevice device(mock_device, mock_vsync);
228+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
229
230 EXPECT_THROW({
231 device.gpu_render(dpy, surf);
232@@ -136,15 +150,19 @@
233 {
234 using namespace testing;
235 int hwc_return_fence = 94;
236+ int hwc_retire_fence = 74;
237 mock_device->hwc_set_return_fence(hwc_return_fence);
238+ mock_device->hwc_set_retire_fence(hwc_retire_fence);
239
240- mga::HwcDevice device(mock_device, mock_vsync);
241+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
242
243 InSequence seq;
244 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), 1, _))
245 .Times(1);
246 EXPECT_CALL(*mock_native_buffer, update_fence(hwc_return_fence))
247 .Times(1);
248+ EXPECT_CALL(*mock_file_ops, close(hwc_retire_fence))
249+ .Times(1);
250
251 device.post(*mock_buffer);
252
253@@ -161,7 +179,7 @@
254 {
255 using namespace testing;
256
257- mga::HwcDevice device(mock_device, mock_vsync);
258+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
259
260 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), _, _))
261 .Times(1)

Subscribers

People subscribed via source and target branches