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
=== modified file 'include/test/mir_test_doubles/mock_hwc_composer_device_1.h'
--- include/test/mir_test_doubles/mock_hwc_composer_device_1.h 2014-01-23 17:26:51 +0000
+++ include/test/mir_test_doubles/mock_hwc_composer_device_1.h 2014-01-31 18:37:40 +0000
@@ -76,6 +76,11 @@
76 fb_fence = fence;76 fb_fence = fence;
77 }77 }
7878
79 void hwc_set_retire_fence(int fence)
80 {
81 retire_fence = fence;
82 }
83
79 int save_last_prepare_arguments(struct hwc_composer_device_1 *, size_t size, hwc_display_contents_1_t** displays)84 int save_last_prepare_arguments(struct hwc_composer_device_1 *, size_t size, hwc_display_contents_1_t** displays)
80 {85 {
81 if ((size == 0) || (!displays)) 86 if ((size == 0) || (!displays))
@@ -122,12 +127,14 @@
122 set_layerlist.back().visibleRegionScreen = {0, nullptr};127 set_layerlist.back().visibleRegionScreen = {0, nullptr};
123 }128 }
124129
130 save_args(&display0_set_content, displays);
131
125 if (displays[0]->numHwLayers >= 2)132 if (displays[0]->numHwLayers >= 2)
126 {133 {
127 displays[0]->hwLayers[1].releaseFenceFd = fb_fence;134 displays[0]->hwLayers[1].releaseFenceFd = fb_fence;
135 displays[0]->retireFenceFd = retire_fence;
128 }136 }
129137
130 save_args(&display0_set_content, displays);
131 default:138 default:
132 break;139 break;
133 }140 }
@@ -186,6 +193,7 @@
186 std::vector<hwc_layer_1> prepare_layerlist;193 std::vector<hwc_layer_1> prepare_layerlist;
187 hwc_display_contents_1_t display0_prepare_content;194 hwc_display_contents_1_t display0_prepare_content;
188 int fb_fence;195 int fb_fence;
196 int retire_fence;
189};197};
190198
191}199}
192200
=== modified file 'src/platform/graphics/android/hwc_device.cpp'
--- src/platform/graphics/android/hwc_device.cpp 2014-01-23 18:01:19 +0000
+++ src/platform/graphics/android/hwc_device.cpp 2014-01-31 18:37:40 +0000
@@ -35,10 +35,11 @@
35namespace geom = mir::geometry;35namespace geom = mir::geometry;
3636
37mga::HwcDevice::HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,37mga::HwcDevice::HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
38 std::shared_ptr<HWCVsyncCoordinator> const& coordinator)38 std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
39 std::shared_ptr<SyncFileOps> const& sync_ops)
39 : HWCCommonDevice(hwc_device, coordinator),40 : HWCCommonDevice(hwc_device, coordinator),
40 layer_list({mga::ForceGLLayer{}, mga::FramebufferLayer{}}),41 layer_list({mga::ForceGLLayer{}, mga::FramebufferLayer{}}),
41 sync_ops(std::make_shared<mga::RealSyncFileOps>())42 sync_ops(sync_ops)
42{43{
43}44}
4445
@@ -79,12 +80,8 @@
79 BOOST_THROW_EXCEPTION(std::runtime_error("error during hwc set()"));80 BOOST_THROW_EXCEPTION(std::runtime_error("error during hwc set()"));
80 }81 }
8182
82 if (last_display_fence)83 mga::SyncFence retire_fence(sync_ops, displays[HWC_DISPLAY_PRIMARY]->retireFenceFd);
83 last_display_fence->wait();
8484
85 int framebuffer_fence = layer_list.framebuffer_fence();85 int framebuffer_fence = layer_list.framebuffer_fence();
86 native_buffer->update_fence(framebuffer_fence);86 native_buffer->update_fence(framebuffer_fence);
87
88 last_display_fence = std::make_shared<mga::SyncFence>(
89 sync_ops, displays[HWC_DISPLAY_PRIMARY]->retireFenceFd);
90}87}
9188
=== modified file 'src/platform/graphics/android/hwc_device.h'
--- src/platform/graphics/android/hwc_device.h 2014-01-23 18:01:19 +0000
+++ src/platform/graphics/android/hwc_device.h 2014-01-31 18:37:40 +0000
@@ -34,13 +34,13 @@
34{34{
35class HWCVsyncCoordinator;35class HWCVsyncCoordinator;
36class SyncFileOps;36class SyncFileOps;
37class SyncFence;
3837
39class HwcDevice : public HWCCommonDevice38class HwcDevice : public HWCCommonDevice
40{39{
41public:40public:
42 HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,41 HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
43 std::shared_ptr<HWCVsyncCoordinator> const& coordinator);42 std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
43 std::shared_ptr<SyncFileOps> const& sync_ops);
4444
45 void prepare_gl();45 void prepare_gl();
46 void prepare_gl_and_overlays(std::list<std::shared_ptr<Renderable>> const& list); 46 void prepare_gl_and_overlays(std::list<std::shared_ptr<Renderable>> const& list);
@@ -50,7 +50,6 @@
50private:50private:
51 LayerList layer_list;51 LayerList layer_list;
5252
53 std::shared_ptr<SyncFence> last_display_fence;
54 std::shared_ptr<SyncFileOps> const sync_ops;53 std::shared_ptr<SyncFileOps> const sync_ops;
55 unsigned int primary_display_config;54 unsigned int primary_display_config;
56 MirPixelFormat fb_format;55 MirPixelFormat fb_format;
5756
=== modified file 'src/platform/graphics/android/resource_factory.cpp'
--- src/platform/graphics/android/resource_factory.cpp 2014-01-21 18:09:35 +0000
+++ src/platform/graphics/android/resource_factory.cpp 2014-01-31 18:37:40 +0000
@@ -18,6 +18,7 @@
18 */18 */
1919
20#include "mir/graphics/android/mir_native_window.h"20#include "mir/graphics/android/mir_native_window.h"
21#include "mir/graphics/android/sync_fence.h"
21#include "buffer.h"22#include "buffer.h"
22#include "resource_factory.h"23#include "resource_factory.h"
23#include "fb_device.h"24#include "fb_device.h"
@@ -91,7 +92,8 @@
91 std::shared_ptr<hwc_composer_device_1> const& hwc_native_device) const92 std::shared_ptr<hwc_composer_device_1> const& hwc_native_device) const
92{93{
93 auto syncer = std::make_shared<mga::HWCVsync>();94 auto syncer = std::make_shared<mga::HWCVsync>();
94 return std::make_shared<mga::HwcDevice>(hwc_native_device, syncer);95 auto file_ops = std::make_shared<mga::RealSyncFileOps>();
96 return std::make_shared<mga::HwcDevice>(hwc_native_device, syncer, file_ops);
95}97}
9698
97std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(99std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(
98100
=== modified file 'tests/unit-tests/graphics/android/test_hwc_common_device.cpp'
--- tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-01-21 18:09:35 +0000
+++ tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-01-31 18:37:40 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>16 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
17 */17 */
1818
19#include "mir/graphics/android/sync_fence.h"
19#include "src/platform/graphics/android/hwc_fb_device.h"20#include "src/platform/graphics/android/hwc_fb_device.h"
20#include "src/platform/graphics/android/hwc_device.h"21#include "src/platform/graphics/android/hwc_device.h"
21#include "src/platform/graphics/android/hwc_layerlist.h"22#include "src/platform/graphics/android/hwc_layerlist.h"
@@ -58,7 +59,8 @@
58 std::shared_ptr<framebuffer_device_t> const&,59 std::shared_ptr<framebuffer_device_t> const&,
59 std::shared_ptr<mga::HWCVsyncCoordinator> const& coordinator)60 std::shared_ptr<mga::HWCVsyncCoordinator> const& coordinator)
60{61{
61 return std::make_shared<mga::HwcDevice>(hwc_device, coordinator);62 auto file_ops = std::make_shared<mga::RealSyncFileOps>();
63 return std::make_shared<mga::HwcDevice>(hwc_device, coordinator, file_ops);
62}64}
6365
64template<typename T>66template<typename T>
6567
=== modified file 'tests/unit-tests/graphics/android/test_hwc_device.cpp'
--- tests/unit-tests/graphics/android/test_hwc_device.cpp 2014-01-23 17:26:51 +0000
+++ tests/unit-tests/graphics/android/test_hwc_device.cpp 2014-01-31 18:37:40 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>16 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
17 */17 */
1818
19#include "mir/graphics/android/sync_fence.h"
19#include "src/platform/graphics/android/framebuffer_bundle.h"20#include "src/platform/graphics/android/framebuffer_bundle.h"
20#include "src/platform/graphics/android/hwc_device.h"21#include "src/platform/graphics/android/hwc_device.h"
21#include "src/platform/graphics/android/hwc_layerlist.h"22#include "src/platform/graphics/android/hwc_layerlist.h"
@@ -35,6 +36,16 @@
35namespace mtd=mir::test::doubles;36namespace mtd=mir::test::doubles;
36namespace geom=mir::geometry;37namespace geom=mir::geometry;
3738
39namespace
40{
41struct MockFileOps : public mga::SyncFileOps
42{
43 MOCK_METHOD3(ioctl, int(int,int,void*));
44 MOCK_METHOD1(dup, int(int));
45 MOCK_METHOD1(close, int(int));
46};
47}
48
38class HwcDevice : public ::testing::Test49class HwcDevice : public ::testing::Test
39{50{
40protected:51protected:
@@ -48,10 +59,13 @@
48 mock_buffer = std::make_shared<testing::NiceMock<mtd::MockBuffer>>();59 mock_buffer = std::make_shared<testing::NiceMock<mtd::MockBuffer>>();
49 mock_device = std::make_shared<testing::NiceMock<mtd::MockHWCComposerDevice1>>();60 mock_device = std::make_shared<testing::NiceMock<mtd::MockHWCComposerDevice1>>();
50 mock_vsync = std::make_shared<testing::NiceMock<mtd::MockVsyncCoordinator>>();61 mock_vsync = std::make_shared<testing::NiceMock<mtd::MockVsyncCoordinator>>();
62 mock_file_ops = std::make_shared<MockFileOps>();
5163
52 ON_CALL(*mock_buffer, native_buffer_handle())64 ON_CALL(*mock_buffer, native_buffer_handle())
53 .WillByDefault(Return(mock_native_buffer));65 .WillByDefault(Return(mock_native_buffer));
54 }66 }
67
68 std::shared_ptr<MockFileOps> mock_file_ops;
55 std::shared_ptr<mtd::MockVsyncCoordinator> mock_vsync;69 std::shared_ptr<mtd::MockVsyncCoordinator> mock_vsync;
56 std::shared_ptr<mtd::MockHWCComposerDevice1> mock_device;70 std::shared_ptr<mtd::MockHWCComposerDevice1> mock_device;
57 std::shared_ptr<mtd::MockAndroidNativeBuffer> mock_native_buffer;71 std::shared_ptr<mtd::MockAndroidNativeBuffer> mock_native_buffer;
@@ -69,7 +83,7 @@
69 EXPECT_CALL(*mock_device, set_interface(mock_device.get(),_,_))83 EXPECT_CALL(*mock_device, set_interface(mock_device.get(),_,_))
70 .Times(1);84 .Times(1);
7185
72 mga::HwcDevice device(mock_device, mock_vsync);86 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
73 device.prepare_gl();87 device.prepare_gl();
74 device.post(*mock_buffer);88 device.post(*mock_buffer);
7589
@@ -90,7 +104,7 @@
90 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))104 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))
91 .Times(1);105 .Times(1);
92106
93 mga::HwcDevice device(mock_device, mock_vsync);107 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
94 device.prepare_gl();108 device.prepare_gl();
95 EXPECT_EQ(2, mock_device->display0_prepare_content.numHwLayers);109 EXPECT_EQ(2, mock_device->display0_prepare_content.numHwLayers);
96 EXPECT_EQ(-1, mock_device->display0_prepare_content.retireFenceFd);110 EXPECT_EQ(-1, mock_device->display0_prepare_content.retireFenceFd);
@@ -102,7 +116,7 @@
102 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))116 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))
103 .Times(1);117 .Times(1);
104118
105 mga::HwcDevice device(mock_device, mock_vsync);119 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
106 std::list<std::shared_ptr<mg::Renderable>> renderlist;120 std::list<std::shared_ptr<mg::Renderable>> renderlist;
107 device.prepare_gl_and_overlays(renderlist);121 device.prepare_gl_and_overlays(renderlist);
108122
@@ -114,7 +128,7 @@
114{128{
115 EXPECT_CALL(mock_egl, eglSwapBuffers(dpy,surf))129 EXPECT_CALL(mock_egl, eglSwapBuffers(dpy,surf))
116 .Times(1);130 .Times(1);
117 mga::HwcDevice device(mock_device, mock_vsync);131 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
118 device.gpu_render(dpy, surf);132 device.gpu_render(dpy, surf);
119}133}
120134
@@ -125,7 +139,7 @@
125 .Times(1)139 .Times(1)
126 .WillOnce(Return(EGL_FALSE));140 .WillOnce(Return(EGL_FALSE));
127141
128 mga::HwcDevice device(mock_device, mock_vsync);142 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
129143
130 EXPECT_THROW({144 EXPECT_THROW({
131 device.gpu_render(dpy, surf);145 device.gpu_render(dpy, surf);
@@ -136,15 +150,19 @@
136{150{
137 using namespace testing;151 using namespace testing;
138 int hwc_return_fence = 94;152 int hwc_return_fence = 94;
153 int hwc_retire_fence = 74;
139 mock_device->hwc_set_return_fence(hwc_return_fence);154 mock_device->hwc_set_return_fence(hwc_return_fence);
155 mock_device->hwc_set_retire_fence(hwc_retire_fence);
140156
141 mga::HwcDevice device(mock_device, mock_vsync);157 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
142158
143 InSequence seq;159 InSequence seq;
144 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), 1, _))160 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), 1, _))
145 .Times(1);161 .Times(1);
146 EXPECT_CALL(*mock_native_buffer, update_fence(hwc_return_fence))162 EXPECT_CALL(*mock_native_buffer, update_fence(hwc_return_fence))
147 .Times(1);163 .Times(1);
164 EXPECT_CALL(*mock_file_ops, close(hwc_retire_fence))
165 .Times(1);
148166
149 device.post(*mock_buffer);167 device.post(*mock_buffer);
150168
@@ -161,7 +179,7 @@
161{179{
162 using namespace testing;180 using namespace testing;
163181
164 mga::HwcDevice device(mock_device, mock_vsync);182 mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
165183
166 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), _, _))184 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), _, _))
167 .Times(1)185 .Times(1)

Subscribers

People subscribed via source and target branches