Mir

Merge lp:~raof/mir/dont-tear-down-compositor-if-unnecessary into lp:mir

Proposed by Chris Halse Rogers
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 3712
Proposed branch: lp:~raof/mir/dont-tear-down-compositor-if-unnecessary
Merge into: lp:mir
Diff against target: 541 lines (+293/-13)
16 files modified
include/platform/mir/graphics/display.h (+18/-0)
include/test/mir/test/doubles/null_display.h (+4/-0)
src/platforms/android/server/display.cpp (+6/-0)
src/platforms/android/server/display.h (+1/-0)
src/platforms/eglstream-kms/server/display.cpp (+6/-0)
src/platforms/eglstream-kms/server/display.h (+2/-0)
src/platforms/mesa/server/kms/display.cpp (+6/-0)
src/platforms/mesa/server/kms/display.h (+1/-0)
src/platforms/mesa/server/x11/graphics/display.cpp (+6/-0)
src/platforms/mesa/server/x11/graphics/display.h (+3/-0)
src/server/graphics/nested/display.cpp (+6/-0)
src/server/graphics/nested/display.h (+3/-0)
src/server/scene/mediating_display_changer.cpp (+37/-4)
tests/include/mir/test/doubles/mock_display.h (+2/-0)
tests/mir_test_framework/stubbed_graphics_platform.cpp (+4/-0)
tests/unit-tests/scene/test_mediating_display_changer.cpp (+188/-9)
To merge this branch: bzr merge lp:~raof/mir/dont-tear-down-compositor-if-unnecessary
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Cemil Azizoglu (community) Approve
Alan Griffiths Approve
Review via email: mp+305778@code.launchpad.net

This proposal supersedes a proposal from 2016-09-09.

Commit message

Prevent unnecessary reinitialisation of the compositor on display configuration (round 1)

We currently need to tear down and reinitialise the compositor on display changes because (a) we have no way of adding or removing compositors short of a full teardown/rebuild cycle and, worse (b) because the compositor takes a non-owning reference to a DisplayBuffer and display configuration will frequently destroy all existing DisplayBuffers.

Add an interface to the platform's Display to check when a display configuration change will *not* destroy existing DisplayBuffers. If it will not, that avoids problem (b), so check if any new outputs have been enabled. If neither of those are the case we can safely apply the display configuration without reinitialising the compositor.

Follow up work will enable this in the various graphics platforms.

Fixes (part one): https://bugs.launchpad.net/mir/+bug/1556142

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:3702
https://mir-jenkins.ubuntu.com/job/mir-ci/1678/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2103/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2165
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2156
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2156
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2156
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2131/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2131
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2131/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2131
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2131/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2131
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2131/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2131
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2131/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1678/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

08:42:03 clang: error: invalid argument '/build/mir' to -fdebug-prefix-map

Again. ???

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:3702
https://mir-jenkins.ubuntu.com/job/mir-ci/1684/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2109/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2171
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2162
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2162
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2162
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2137/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2137
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2137/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2137
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2137/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2137
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2137/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2137
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2137/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1684/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:3704
https://mir-jenkins.ubuntu.com/job/mir-ci/1698/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2126/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2188
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2179
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2179
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2179
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2154
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2154/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2154
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2154/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2154/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2154
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2154/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2154
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2154/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1698/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

02:05:53 cc1plus: error: invalid argument ���/build/mir��� to -fdebug-prefix-map
Retriggering

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:3704
https://mir-jenkins.ubuntu.com/job/mir-ci/1699/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2127
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2189
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2180
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2180
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2180
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2155
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2155/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2155
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2155/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2155
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2155/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2155
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2155/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2155
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2155/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1699/rebuild

review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

+ virtual bool configuration_will_preserve_display_buffers(DisplayConfiguration const& conf) const = 0;

While not an issue in the current usage I worry that this style invites racy code. I would prefer something that's obviously atomic:

 bool apply_configuration_if_it_preserves_display_buffers(DisplayConfiguration const& conf) const = 0;

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> + virtual bool
> configuration_will_preserve_display_buffers(DisplayConfiguration const& conf)
> const = 0;
>
> While not an issue in the current usage I worry that this style invites racy
> code. I would prefer something that's obviously atomic:
>
> bool apply_configuration_if_it_preserves_display_buffers(DisplayConfiguration
> const& conf) const = 0;

I'm not going to block on this, but please consider it before TA.

review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

Hm.

It's pretty easy to use correctly now - the results of will_preserve_display_buffers() are valid until the next configure() call, we serialize all of those, and they're easy to notice.

But apply_configuration_if_it_preserves_display_buffers() would indeed be even easier to use correctly, and might even be easier to implement in the platforms. Thanks for the review!

Revision history for this message
Chris Halse Rogers (raof) wrote :

Now with atomic test-and-set semantics.

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3711
https://mir-jenkins.ubuntu.com/job/mir-ci/1721/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2151/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2214
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2205
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2205
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2205
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2179/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2179/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2179/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2179/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2179
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2179/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1721/rebuild

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

^^^
Just the usual bug 1523621

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

Looks good

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3711
https://mir-jenkins.ubuntu.com/job/mir-ci/1766/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2213/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2276
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2267
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2267
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2267
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2241/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2241/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2241
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2241/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2241
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2241/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2241
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2241/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/1766/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

lgtmt

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

^^^
Jenkins failures are just bug 1523621 as usual.

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Autolanding.
More details in the following jenkins job:
https://mir-jenkins.ubuntu.com/job/mir-autolanding/602/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2225/console
    None: https://mir-jenkins.ubuntu.com/job/generic-land-mp/642/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2288
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2279
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2279
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2279
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2253
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2253/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2253/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2253
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2253/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2253
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2253/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2253
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2253/artifact/output/*zip*/output.zip

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

^^^
Bug 1523621 again

Revision history for this message
Mir CI Bot (mir-ci-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/platform/mir/graphics/display.h'
2--- include/platform/mir/graphics/display.h 2016-09-08 15:28:25 +0000
3+++ include/platform/mir/graphics/display.h 2016-09-15 01:44:40 +0000
4@@ -110,6 +110,24 @@
5 virtual std::unique_ptr<DisplayConfiguration> configuration() const = 0;
6
7 /**
8+ * Applying a display configuration only if it will not invalidate existing DisplayBuffers
9+ *
10+ * The Display must guarantee that the references to the DisplayBuffer acquired via
11+ * DisplaySyncGroup::for_each_display_buffer() remain valid until the Display is destroyed or
12+ * Display::configure() is called.
13+ *
14+ * If this function returns \c true then the new display configuration has been applied.
15+ * If this function returns \c false then the new display configuration has not been applied.
16+ *
17+ * In either case this function guarantees that existing DisplayBuffer references will remain
18+ * valid.
19+ *
20+ * \param conf [in] Configuration to possibly apply.
21+ * \return \c true if \p conf has been applied as the new output configuration.
22+ */
23+ virtual bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const = 0;
24+
25+ /**
26 * Sets a new output configuration.
27 */
28 virtual void configure(DisplayConfiguration const& conf) = 0;
29
30=== modified file 'include/test/mir/test/doubles/null_display.h'
31--- include/test/mir/test/doubles/null_display.h 2016-08-01 09:37:45 +0000
32+++ include/test/mir/test/doubles/null_display.h 2016-09-15 01:44:40 +0000
33@@ -48,6 +48,10 @@
34 new NullDisplayConfiguration
35 );
36 }
37+ bool apply_if_configuration_preserves_display_buffers(graphics::DisplayConfiguration const&) const override
38+ {
39+ return false;
40+ }
41 void configure(graphics::DisplayConfiguration const&) override{}
42 void register_configuration_change_handler(
43 graphics::EventHandlerRegister&,
44
45=== modified file 'src/platforms/android/server/display.cpp'
46--- src/platforms/android/server/display.cpp 2016-08-01 09:37:45 +0000
47+++ src/platforms/android/server/display.cpp 2016-09-15 01:44:40 +0000
48@@ -358,3 +358,9 @@
49 {
50 return std::make_unique<mga::PbufferGLContext>(gl_context);
51 }
52+
53+bool mga::Display::apply_if_configuration_preserves_display_buffers(
54+ mg::DisplayConfiguration const& /*conf*/) const
55+{
56+ return false;
57+}
58
59=== modified file 'src/platforms/android/server/display.h'
60--- src/platforms/android/server/display.h 2016-08-01 09:37:45 +0000
61+++ src/platforms/android/server/display.h 2016-09-15 01:44:40 +0000
62@@ -66,6 +66,7 @@
63 void for_each_display_sync_group(std::function<void(graphics::DisplaySyncGroup&)> const& f) override;
64
65 std::unique_ptr<graphics::DisplayConfiguration> configuration() const override;
66+ bool apply_if_configuration_preserves_display_buffers(graphics::DisplayConfiguration const& conf) const override;
67 void configure(graphics::DisplayConfiguration const&) override;
68
69 void register_configuration_change_handler(
70
71=== modified file 'src/platforms/eglstream-kms/server/display.cpp'
72--- src/platforms/eglstream-kms/server/display.cpp 2016-08-01 09:37:45 +0000
73+++ src/platforms/eglstream-kms/server/display.cpp 2016-09-15 01:44:40 +0000
74@@ -367,3 +367,9 @@
75 return std::make_unique<GLContext>(display, context);
76 }
77
78+bool mge::Display::apply_if_configuration_preserves_display_buffers(
79+ mg::DisplayConfiguration const& /*conf*/) const
80+{
81+ return false;
82+}
83+
84
85=== modified file 'src/platforms/eglstream-kms/server/display.h'
86--- src/platforms/eglstream-kms/server/display.h 2016-08-01 09:37:45 +0000
87+++ src/platforms/eglstream-kms/server/display.h 2016-09-15 01:44:40 +0000
88@@ -49,6 +49,8 @@
89
90 std::unique_ptr<DisplayConfiguration> configuration() const override;
91
92+ bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const override;
93+
94 void configure(DisplayConfiguration const& conf) override;
95
96 void register_configuration_change_handler(EventHandlerRegister& handlers,
97
98=== modified file 'src/platforms/mesa/server/kms/display.cpp'
99--- src/platforms/mesa/server/kms/display.cpp 2016-08-23 20:21:27 +0000
100+++ src/platforms/mesa/server/kms/display.cpp 2016-09-15 01:44:40 +0000
101@@ -415,3 +415,9 @@
102 {
103 return std::make_unique<GBMGLContext>(*gbm, *gl_config, shared_egl.context());
104 }
105+
106+bool mgm::Display::apply_if_configuration_preserves_display_buffers(
107+ mg::DisplayConfiguration const& /*conf*/) const
108+{
109+ return false;
110+}
111
112=== modified file 'src/platforms/mesa/server/kms/display.h'
113--- src/platforms/mesa/server/kms/display.h 2016-08-01 09:37:45 +0000
114+++ src/platforms/mesa/server/kms/display.h 2016-09-15 01:44:40 +0000
115@@ -78,6 +78,7 @@
116 std::function<void(graphics::DisplaySyncGroup&)> const& f) override;
117
118 std::unique_ptr<DisplayConfiguration> configuration() const override;
119+ bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const override;
120 void configure(DisplayConfiguration const& conf) override;
121
122 void register_configuration_change_handler(
123
124=== modified file 'src/platforms/mesa/server/x11/graphics/display.cpp'
125--- src/platforms/mesa/server/x11/graphics/display.cpp 2016-09-07 04:54:17 +0000
126+++ src/platforms/mesa/server/x11/graphics/display.cpp 2016-09-15 01:44:40 +0000
127@@ -380,3 +380,9 @@
128 {
129 return std::make_unique<mgx::XGLContext>(egl_display, egl_surface, egl_context);
130 }
131+
132+bool mgx::Display::apply_if_configuration_preserves_display_buffers(
133+ mg::DisplayConfiguration const& /*conf*/) const
134+{
135+ return false;
136+}
137
138=== modified file 'src/platforms/mesa/server/x11/graphics/display.h'
139--- src/platforms/mesa/server/x11/graphics/display.h 2016-09-07 03:37:03 +0000
140+++ src/platforms/mesa/server/x11/graphics/display.h 2016-09-15 01:44:40 +0000
141@@ -111,6 +111,9 @@
142 void for_each_display_sync_group(std::function<void(graphics::DisplaySyncGroup&)> const& f) override;
143
144 std::unique_ptr<graphics::DisplayConfiguration> configuration() const override;
145+
146+ bool apply_if_configuration_preserves_display_buffers(graphics::DisplayConfiguration const& conf) const override;
147+
148 void configure(graphics::DisplayConfiguration const&) override;
149
150 void register_configuration_change_handler(
151
152=== modified file 'src/server/graphics/nested/display.cpp'
153--- src/server/graphics/nested/display.cpp 2016-08-25 12:50:09 +0000
154+++ src/server/graphics/nested/display.cpp 2016-09-15 01:44:40 +0000
155@@ -366,3 +366,9 @@
156 {
157 return egl_display.create_gl_context();
158 }
159+
160+bool mgn::Display::apply_if_configuration_preserves_display_buffers(
161+ mg::DisplayConfiguration const& /*conf*/) const
162+{
163+ return false;
164+}
165
166=== modified file 'src/server/graphics/nested/display.h'
167--- src/server/graphics/nested/display.h 2016-08-01 09:37:45 +0000
168+++ src/server/graphics/nested/display.h 2016-09-15 01:44:40 +0000
169@@ -128,6 +128,9 @@
170 void for_each_display_sync_group(std::function<void(DisplaySyncGroup&)>const& f) override;
171
172 std::unique_ptr<DisplayConfiguration> configuration() const override;
173+
174+ bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const override;
175+
176 void configure(DisplayConfiguration const&) override;
177
178 void register_configuration_change_handler(
179
180=== modified file 'src/server/scene/mediating_display_changer.cpp'
181--- src/server/scene/mediating_display_changer.cpp 2016-09-12 02:58:30 +0000
182+++ src/server/scene/mediating_display_changer.cpp 2016-09-15 01:44:40 +0000
183@@ -18,6 +18,7 @@
184
185 #include <condition_variable>
186 #include <boost/throw_exception.hpp>
187+#include <unordered_set>
188 #include "mediating_display_changer.h"
189 #include "session_container.h"
190 #include "mir/scene/session.h"
191@@ -330,15 +331,47 @@
192 server_action_queue->resume_processing_for(this);
193 }
194
195+namespace
196+{
197+bool configuration_has_new_outputs_enabled(
198+ mg::DisplayConfiguration const& existing,
199+ mg::DisplayConfiguration const& updated)
200+{
201+ std::unordered_set<mg::DisplayConfigurationOutputId> currently_enabled_outputs;
202+ existing.for_each_output(
203+ [&currently_enabled_outputs](auto const& output)
204+ {
205+ if (output.used)
206+ {
207+ currently_enabled_outputs.insert(output.id);
208+ }
209+ });
210+ bool has_new_output{false};
211+ updated.for_each_output(
212+ [&currently_enabled_outputs, &has_new_output](auto const& output)
213+ {
214+ if (output.used)
215+ {
216+ has_new_output |= (currently_enabled_outputs.count(output.id) == 0);
217+ }
218+ });
219+ return has_new_output;
220+}
221+}
222+
223 void ms::MediatingDisplayChanger::apply_config(
224 std::shared_ptr<graphics::DisplayConfiguration> const& conf)
225 {
226 report->new_configuration(*conf);
227- ApplyNowAndRevertOnScopeExit comp{
228- [this] { compositor->stop(); },
229- [this] { compositor->start(); }};
230
231- display->configure(*conf);
232+ if (configuration_has_new_outputs_enabled(*display->configuration(), *conf) ||
233+ !display->apply_if_configuration_preserves_display_buffers(*conf))
234+ {
235+ ApplyNowAndRevertOnScopeExit comp{
236+ [this] { compositor->stop(); },
237+ [this] { compositor->start(); }};
238+ display->configure(*conf);
239+ }
240 update_input_rectangles(*conf);
241
242 base_configuration_applied = false;
243
244=== modified file 'tests/include/mir/test/doubles/mock_display.h'
245--- tests/include/mir/test/doubles/mock_display.h 2016-08-01 09:37:45 +0000
246+++ tests/include/mir/test/doubles/mock_display.h 2016-09-15 01:44:40 +0000
247@@ -37,6 +37,8 @@
248 public:
249 MOCK_METHOD1(for_each_display_sync_group, void (std::function<void(graphics::DisplaySyncGroup&)> const&));
250 MOCK_CONST_METHOD0(configuration, std::unique_ptr<graphics::DisplayConfiguration>());
251+ MOCK_CONST_METHOD1(apply_if_configuration_preserves_display_buffers, bool(graphics::DisplayConfiguration const
252+ &));
253 MOCK_METHOD1(configure, void(graphics::DisplayConfiguration const&));
254 MOCK_METHOD2(register_configuration_change_handler,
255 void(graphics::EventHandlerRegister&, graphics::DisplayConfigurationChangeHandler const&));
256
257=== modified file 'tests/mir_test_framework/stubbed_graphics_platform.cpp'
258--- tests/mir_test_framework/stubbed_graphics_platform.cpp 2016-09-13 08:09:53 +0000
259+++ tests/mir_test_framework/stubbed_graphics_platform.cpp 2016-09-15 01:44:40 +0000
260@@ -62,6 +62,10 @@
261 {
262 return display->configuration();
263 }
264+ bool apply_if_configuration_preserves_display_buffers(mg::DisplayConfiguration const& /*conf*/) const override
265+ {
266+ return false;
267+ }
268 void configure(mg::DisplayConfiguration const& conf) override
269 {
270 display->configure(conf);
271
272=== modified file 'tests/unit-tests/scene/test_mediating_display_changer.cpp'
273--- tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-09-12 02:58:30 +0000
274+++ tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-09-15 01:44:40 +0000
275@@ -209,12 +209,15 @@
276 EXPECT_THAT(*base_conf, mt::DisplayConfigMatches(std::ref(*mock_display.conf_ptr)));
277 }
278
279-TEST_F(MediatingDisplayChangerTest, pauses_system_when_applying_new_configuration_for_focused_session)
280+TEST_F(MediatingDisplayChangerTest, pauses_system_when_applying_new_configuration_for_focused_session_would_invalidate_display_buffers)
281 {
282 using namespace testing;
283 mtd::NullDisplayConfiguration conf;
284 auto session = std::make_shared<mtd::StubSession>();
285
286+ ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_))
287+ .WillByDefault(Return(false));
288+
289 InSequence s;
290 EXPECT_CALL(mock_compositor, stop());
291
292@@ -227,13 +230,32 @@
293 mt::fake_shared(conf));
294 }
295
296+TEST_F(MediatingDisplayChangerTest, does_not_pause_system_when_applying_new_configuration_for_focused_session_would_preserve_display_buffers)
297+{
298+ using namespace testing;
299+ mtd::NullDisplayConfiguration conf;
300+ auto session = std::make_shared<mtd::StubSession>();
301+
302+ EXPECT_CALL(mock_display, apply_if_configuration_preserves_display_buffers(Ref(conf)))
303+ .WillOnce(Return(true));
304+
305+ EXPECT_CALL(mock_compositor, stop()).Times(0);
306+ EXPECT_CALL(mock_compositor, start()).Times(0);
307+ EXPECT_CALL(mock_display, configure(_)).Times(0);
308+
309+ session_event_sink.handle_focus_change(session);
310+ changer->configure(session,
311+ mt::fake_shared(conf));
312+}
313+
314+
315 TEST_F(MediatingDisplayChangerTest, doesnt_apply_config_for_unfocused_session)
316 {
317 using namespace testing;
318 mtd::NullDisplayConfiguration conf;
319
320 EXPECT_CALL(mock_compositor, stop()).Times(0);
321- EXPECT_CALL(mock_display, configure(Ref(conf))).Times(0);
322+ EXPECT_CALL(mock_display, configure(_)).Times(0);
323 EXPECT_CALL(mock_compositor, start()).Times(0);
324
325 changer->configure(std::make_shared<mtd::StubSession>(),
326@@ -253,11 +275,14 @@
327 EXPECT_THAT(*base_conf, mt::DisplayConfigMatches(conf));
328 }
329
330-TEST_F(MediatingDisplayChangerTest, handles_hardware_change_properly_when_pausing_system)
331+TEST_F(MediatingDisplayChangerTest, handles_hardware_change_when_display_buffers_are_invalidated)
332 {
333 using namespace testing;
334 mtd::NullDisplayConfiguration conf;
335
336+ ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_))
337+ .WillByDefault(Return(false));
338+
339 InSequence s;
340 EXPECT_CALL(mock_conf_policy, apply_to(Ref(conf)));
341
342@@ -268,6 +293,61 @@
343 changer->configure_for_hardware_change(mt::fake_shared(conf));
344 }
345
346+TEST_F(MediatingDisplayChangerTest, handles_hardware_change_when_display_buffers_are_preserved)
347+{
348+ using namespace testing;
349+ mtd::NullDisplayConfiguration conf;
350+
351+ {
352+ InSequence s;
353+ EXPECT_CALL(mock_conf_policy, apply_to(Ref(conf)));
354+
355+ EXPECT_CALL(mock_display, apply_if_configuration_preserves_display_buffers(Ref(conf)))
356+ .WillOnce(Return(true));
357+ }
358+
359+ EXPECT_CALL(mock_compositor, stop()).Times(0);
360+ EXPECT_CALL(mock_display, configure(_)).Times(0);
361+ EXPECT_CALL(mock_compositor, start()).Times(0);
362+
363+ changer->configure_for_hardware_change(mt::fake_shared(conf));
364+}
365+
366+TEST_F(MediatingDisplayChangerTest, handles_hardware_change_when_display_buffers_are_preserved_but_new_outputs_are_enabled)
367+{
368+ using namespace testing;
369+
370+ auto conf = changer->base_configuration();
371+
372+ bool new_output_enabled{false};
373+ conf->for_each_output(
374+ [&new_output_enabled](mg::UserDisplayConfigurationOutput& output)
375+ {
376+ if (!output.used)
377+ {
378+ new_output_enabled = true;
379+ output.used = true;
380+ }
381+ });
382+ ASSERT_TRUE(new_output_enabled);
383+
384+ ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_))
385+ .WillByDefault(Return(true));
386+
387+ InSequence s;
388+ EXPECT_CALL(mock_conf_policy, apply_to(Ref(*conf)));
389+
390+ /*
391+ * Currently we have to tear down and recreate the compositor in order to add
392+ * a new output. This is not an inherent limitation, and we might do better later.
393+ */
394+ EXPECT_CALL(mock_compositor, stop()).Times(1);
395+ EXPECT_CALL(mock_display, configure(Ref(*conf)));
396+ EXPECT_CALL(mock_compositor, start()).Times(1);
397+
398+ changer->configure_for_hardware_change(conf);
399+}
400+
401 TEST_F(MediatingDisplayChangerTest, hardware_change_doesnt_apply_base_config_if_per_session_config_is_active)
402 {
403 using namespace testing;
404@@ -307,11 +387,70 @@
405 changer->configure_for_hardware_change(mt::fake_shared(conf));
406 }
407
408-TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_attached_config_applies_config)
409-{
410- using namespace testing;
411- auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
412- auto session1 = std::make_shared<mtd::StubSession>();
413+TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_db_preserving_attached_config_applies_config)
414+{
415+ using namespace testing;
416+ auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
417+ auto session1 = std::make_shared<mtd::StubSession>();
418+
419+ stub_session_container.insert_session(session1);
420+ changer->configure(session1, conf);
421+
422+ EXPECT_CALL(mock_display, apply_if_configuration_preserves_display_buffers(Ref(*conf)))
423+ .WillOnce(Return(true));
424+
425+ EXPECT_CALL(mock_compositor, stop()).Times(0);
426+ EXPECT_CALL(mock_display, configure(_)).Times(0);
427+ EXPECT_CALL(mock_compositor, start()).Times(0);
428+
429+ session_event_sink.handle_focus_change(session1);
430+}
431+
432+TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_db_preserving_but_output_adding_attached_config_applies_config)
433+{
434+ using namespace testing;
435+ auto session1 = std::make_shared<mtd::StubSession>();
436+
437+ auto conf = changer->base_configuration();
438+
439+ bool new_output_enabled{false};
440+ conf->for_each_output(
441+ [&new_output_enabled](mg::UserDisplayConfigurationOutput& output)
442+ {
443+ if (!output.used)
444+ {
445+ new_output_enabled = true;
446+ output.used = true;
447+ }
448+ });
449+ ASSERT_TRUE(new_output_enabled);
450+
451+ ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_))
452+ .WillByDefault(Return(true));
453+
454+ stub_session_container.insert_session(session1);
455+ changer->configure(session1, conf);
456+
457+ /*
458+ * Currently we have to tear down and recreate the compositor in order to add
459+ * a new output. This is not an inherent limitation, and we might do better later.
460+ */
461+ InSequence s;
462+ EXPECT_CALL(mock_compositor, stop()).Times(1);
463+ EXPECT_CALL(mock_display, configure(Ref(*conf)));
464+ EXPECT_CALL(mock_compositor, start()).Times(1);
465+
466+ session_event_sink.handle_focus_change(session1);
467+}
468+
469+TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_db_invalidating_attached_config_applies_config)
470+{
471+ using namespace testing;
472+ auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
473+ auto session1 = std::make_shared<mtd::StubSession>();
474+
475+ ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_))
476+ .WillByDefault(Return(false));
477
478 stub_session_container.insert_session(session1);
479 changer->configure(session1, conf);
480@@ -324,13 +463,16 @@
481 session_event_sink.handle_focus_change(session1);
482 }
483
484-TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config)
485+TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config_pausing_if_db_invalidated)
486 {
487 using namespace testing;
488 auto conf = std::make_shared<mtd::NullDisplayConfiguration>();
489 auto session1 = std::make_shared<mtd::StubSession>();
490 auto session2 = std::make_shared<mtd::StubSession>();
491
492+ ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_))
493+ .WillByDefault(Return(false));
494+
495 stub_session_container.insert_session(session1);
496 changer->configure(session1, conf);
497
498@@ -347,6 +489,43 @@
499 session_event_sink.handle_focus_change(session2);
500 }
501
502+TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config_not_pausing_if_db_preserved)
503+{
504+ using namespace testing;
505+ std::shared_ptr<mg::DisplayConfiguration> conf = base_config.clone();
506+ conf->for_each_output(
507+ [](mg::UserDisplayConfigurationOutput& output)
508+ {
509+ if (output.used)
510+ {
511+ output.orientation =
512+ output.orientation == mir_orientation_normal ? mir_orientation_left : mir_orientation_normal;
513+ }
514+ });
515+
516+ auto session1 = std::make_shared<mtd::StubSession>();
517+ auto session2 = std::make_shared<mtd::StubSession>();
518+
519+ stub_session_container.insert_session(session1);
520+ changer->configure(session1, conf);
521+
522+ session_event_sink.handle_focus_change(session1);
523+
524+ Mock::VerifyAndClearExpectations(&mock_compositor);
525+ Mock::VerifyAndClearExpectations(&mock_display);
526+
527+ EXPECT_CALL(
528+ mock_display,
529+ apply_if_configuration_preserves_display_buffers(mt::DisplayConfigMatches(std::cref(base_config))))
530+ .WillOnce(Return(true));
531+
532+ EXPECT_CALL(mock_compositor, stop()).Times(0);
533+ EXPECT_CALL(mock_display, configure(_)).Times(0);
534+ EXPECT_CALL(mock_compositor, start()).Times(0);
535+
536+ session_event_sink.handle_focus_change(session2);
537+}
538+
539 TEST_F(MediatingDisplayChangerTest, losing_focus_applies_base_config)
540 {
541 using namespace testing;

Subscribers

People subscribed via source and target branches