Mir

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

Proposed by Kevin DuBois
Status: Merged
Approved by: Kevin DuBois
Approved revision: no longer in the source branch.
Merged at revision: 1320
Proposed branch: lp:~kdub/mir/fix-1238695
Merge into: lp:mir
Diff against target: 124 lines (+56/-13)
3 files modified
src/platform/graphics/android/buffer.cpp (+19/-10)
src/platform/graphics/android/buffer.h (+3/-3)
tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp (+34/-0)
To merge this branch: bzr merge lp:~kdub/mir/fix-1238695
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Gerry Boland (community) functional Approve
Andreas Pokorny (community) Approve
Alan Griffiths Needs Fixing
Alexandros Frantzis (community) Approve
Daniel van Vugt Approve
Kevin DuBois Pending
Review via email: mp+200754@code.launchpad.net

Commit message

Fix: unity8 display flickers and stops responding on Nexus 7 grouper (LP: #1238695)

It seems the issue with the nexus 7 was that its driver had a tough time binding one EGLImage object to two different gl contexts at the same time. This is why the screenshotting thread could mess up the compositing thread and cause the flickering in the bug. If we have two sibling EGLImage objects pointing to the same underlying buffer, we can bind them as textures in both the compositing and screenshotting thread without problems.

Description of the change

It seems the issue with the nexus 7 was that its driver had a tough time binding one EGLImage object to two different gl contexts at the same time. This is why the screenshotting thread could mess up the compositing thread and cause the flickering in the bug. If we have two sibling EGLImage objects pointing to the same underlying buffer, we can bind them as textures in both the compositing and screenshotting thread without problems.

this is indeed a workaround, but its pretty palatable.

tested on nexus 4, galaxy nexus, nexus 7, and nexus 10

fixes: LP: #1238695 LP: #1263741 LP: #1265787

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:1316
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~kdub/mir/fix-1238695/+merge/200754/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-ci/630/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-android-trusty-i386-build/583/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-trusty-amd64-build/579
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-trusty-touch/187
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-amd64-ci/356
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-amd64-ci/356/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-armhf-ci/359
        deb: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-trusty-armhf-ci/359/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-trusty-armhf/187
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-trusty-armhf/187/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-mako/209
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/2804

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-team-mir-development-branch-ci/630/rebuild

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

(1) for(auto it = egl_image_map.begin(); it != egl_image_map.end(); it++)
could be:
    for (auto it& : egl_image_map)
But that's not important.

Looks OK and tested on N7 too.

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

Looks good. Also fixes N10 snapshotting issues.

+1 for "for (auto& it : egl_image_map)" but not critical.

Retriggering build.

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

95 + EGLDisplay disp1 = reinterpret_cast<EGLDisplay>(0x43);
96 + EGLDisplay disp2 = reinterpret_cast<EGLDisplay>(0x88);
97 + EGLContext ctxt1 = reinterpret_cast<EGLContext>(0x11);
98 + EGLContext ctxt2 = reinterpret_cast<EGLContext>(0x12);

Casting arbitrary integers to pointers can lead to undefined behavior. I know we're unlikely to be targeting a platform that, for example, faults on loading an invalid pointer into a register but why not just use the addresses of local variables and avoid the risk?

PS +1 for "for (auto& it : egl_image_map)"

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

> 95 + EGLDisplay disp1 = reinterpret_cast<EGLDisplay>(0x43);
> 96 + EGLDisplay disp2 = reinterpret_cast<EGLDisplay>(0x88);
> 97 + EGLContext ctxt1 = reinterpret_cast<EGLContext>(0x11);
> 98 + EGLContext ctxt2 = reinterpret_cast<EGLContext>(0x12);
>
> Casting arbitrary integers to pointers can lead to undefined behavior. I know
> we're unlikely to be targeting a platform that, for example, faults on loading
> an invalid pointer into a register but why not just use the addresses of local
> variables and avoid the risk?

e.g.

auto const disp1 = static_cast<EGLDisplay>(&disp1);

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

LGTM

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

Functional testing this on Nexus10 shows it working well, the bug is fixed. Nice one!

review: Approve (functional)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

flaky test

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/platform/graphics/android/buffer.cpp'
--- src/platform/graphics/android/buffer.cpp 2013-12-18 02:19:19 +0000
+++ src/platform/graphics/android/buffer.cpp 2014-01-08 16:28:01 +0000
@@ -42,14 +42,13 @@
4242
43mga::Buffer::~Buffer()43mga::Buffer::~Buffer()
44{44{
45 std::map<EGLDisplay,EGLImageKHR>::iterator it;45 for(auto& it : egl_image_map)
46 for(it = egl_image_map.begin(); it != egl_image_map.end(); it++)
47 {46 {
48 egl_extensions->eglDestroyImageKHR(it->first, it->second);47 EGLDisplay disp = it.first.first;
48 egl_extensions->eglDestroyImageKHR(disp, it.second);
49 }49 }
50}50}
5151
52
53geom::Size mga::Buffer::size() const52geom::Size mga::Buffer::size() const
54{53{
55 ANativeWindowBuffer *anwb = native_buffer->anwb();54 ANativeWindowBuffer *anwb = native_buffer->anwb();
@@ -79,26 +78,36 @@
79 std::unique_lock<std::mutex> lk(content_lock);78 std::unique_lock<std::mutex> lk(content_lock);
80 native_buffer->wait_for_content();79 native_buffer->wait_for_content();
8180
82 EGLDisplay disp = eglGetCurrentDisplay();81 DispContextPair current
83 if (disp == EGL_NO_DISPLAY) {82 {
83 eglGetCurrentDisplay(),
84 eglGetCurrentContext()
85 };
86
87 if (current.first == EGL_NO_DISPLAY)
88 {
84 BOOST_THROW_EXCEPTION(std::runtime_error("cannot bind buffer to texture without EGL context\n"));89 BOOST_THROW_EXCEPTION(std::runtime_error("cannot bind buffer to texture without EGL context\n"));
85 }90 }
91
86 static const EGLint image_attrs[] =92 static const EGLint image_attrs[] =
87 {93 {
88 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,94 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
89 EGL_NONE95 EGL_NONE
90 };96 };
97
91 EGLImageKHR image;98 EGLImageKHR image;
92 auto it = egl_image_map.find(disp);99 auto it = egl_image_map.find(current);
93 if (it == egl_image_map.end())100 if (it == egl_image_map.end())
94 {101 {
95 image = egl_extensions->eglCreateImageKHR(disp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,102 image = egl_extensions->eglCreateImageKHR(
96 native_buffer->anwb(), image_attrs);103 current.first, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
104 native_buffer->anwb(), image_attrs);
105
97 if (image == EGL_NO_IMAGE_KHR)106 if (image == EGL_NO_IMAGE_KHR)
98 {107 {
99 BOOST_THROW_EXCEPTION(std::runtime_error("error binding buffer to texture\n"));108 BOOST_THROW_EXCEPTION(std::runtime_error("error binding buffer to texture\n"));
100 }109 }
101 egl_image_map[disp] = image;110 egl_image_map[current] = image;
102 }111 }
103 else /* already had it in map */112 else /* already had it in map */
104 {113 {
105114
=== modified file 'src/platform/graphics/android/buffer.h'
--- src/platform/graphics/android/buffer.h 2013-12-18 02:19:19 +0000
+++ src/platform/graphics/android/buffer.h 2014-01-08 16:28:01 +0000
@@ -58,10 +58,10 @@
58 std::shared_ptr<NativeBuffer> native_buffer_handle() const;58 std::shared_ptr<NativeBuffer> native_buffer_handle() const;
5959
60private:60private:
61 typedef std::pair<EGLDisplay, EGLContext> DispContextPair;
62 std::map<DispContextPair,EGLImageKHR> egl_image_map;
63
61 std::mutex mutable content_lock;64 std::mutex mutable content_lock;
62
63 std::map<EGLDisplay,EGLImageKHR> egl_image_map;
64
65 std::shared_ptr<NativeBuffer> native_buffer;65 std::shared_ptr<NativeBuffer> native_buffer;
66 std::shared_ptr<EGLExtensions> egl_extensions;66 std::shared_ptr<EGLExtensions> egl_extensions;
67};67};
6868
=== modified file 'tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp'
--- tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp 2013-12-18 02:19:19 +0000
+++ tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp 2014-01-08 16:28:01 +0000
@@ -349,3 +349,37 @@
349 mga::Buffer buffer(mock_native_buffer, extensions);349 mga::Buffer buffer(mock_native_buffer, extensions);
350 buffer.bind_to_texture();350 buffer.bind_to_texture();
351}351}
352
353TEST_F(AndroidBufferBinding, different_egl_contexts_displays_generate_new_eglimages)
354{
355 using namespace testing;
356
357 int d1 = 0, d2 = 0, c1 = 0, c2 = 0;
358 EGLDisplay disp1 = reinterpret_cast<EGLDisplay>(&d1);
359 EGLDisplay disp2 = reinterpret_cast<EGLDisplay>(&d2);
360 EGLContext ctxt1 = reinterpret_cast<EGLContext>(&c1);
361 EGLContext ctxt2 = reinterpret_cast<EGLContext>(&c2);
362
363 EXPECT_CALL(mock_egl, eglGetCurrentDisplay())
364 .Times(3)
365 .WillOnce(Return(disp1))
366 .WillOnce(Return(disp1))
367 .WillOnce(Return(disp2));
368
369 EXPECT_CALL(mock_egl, eglGetCurrentContext())
370 .Times(3)
371 .WillOnce(Return(ctxt1))
372 .WillRepeatedly(Return(ctxt2));
373
374 EXPECT_CALL(mock_egl, eglCreateImageKHR(disp1,_,_,_,_))
375 .Times(2);
376 EXPECT_CALL(mock_egl, eglCreateImageKHR(disp2,_,_,_,_))
377 .Times(1);
378 EXPECT_CALL(mock_egl, eglDestroyImageKHR(_,_))
379 .Times(Exactly(3));
380
381 mga::Buffer buffer(mock_native_buffer, extensions);
382 buffer.bind_to_texture();
383 buffer.bind_to_texture();
384 buffer.bind_to_texture();
385}

Subscribers

People subscribed via source and target branches