Mir

Merge lp:mir/0.17 into lp:mir/ubuntu

Proposed by Alberto Aguirre
Status: Merged
Approved by: Alberto Aguirre
Approved revision: 3022
Merged at revision: 1249
Proposed branch: lp:mir/0.17
Merge into: lp:mir/ubuntu
Diff against target: 865 lines (+427/-65)
23 files modified
CMakeLists.txt (+1/-1)
debian/changelog (+20/-0)
debian/control (+1/-0)
debian/mir-client-platform-mesa-dev.install (+1/-0)
include/platform/mir/graphics/display_configuration.h (+3/-0)
src/platform/graphics/display_configuration.cpp (+23/-0)
src/platforms/android/client/android_client_platform.cpp (+3/-14)
src/platforms/common/client/mir/CMakeLists.txt (+1/-0)
src/platforms/common/client/mir/weak_egl.cpp (+65/-0)
src/platforms/common/client/mir/weak_egl.h (+47/-0)
src/platforms/mesa/CMakeLists.txt (+10/-1)
src/platforms/mesa/client/client_platform.cpp (+6/-17)
src/platforms/mesa/mir-client-platform-mesa-dev.pc.in (+1/-1)
src/platforms/mesa/mir-client-platform-mesa.pc.in (+7/-0)
src/server/graphics/nested/display.cpp (+39/-6)
src/server/graphics/nested/display.h (+6/-0)
src/server/input/display_input_region.cpp (+4/-1)
src/server/scene/rendering_tracker.cpp (+12/-0)
src/server/scene/rendering_tracker.h (+2/-1)
src/server/scene/surface_stack.cpp (+11/-8)
tests/acceptance-tests/test_nested_mir.cpp (+109/-15)
tests/unit-tests/input/test_display_input_region.cpp (+11/-0)
tests/unit-tests/scene/test_surface_stack.cpp (+44/-0)
To merge this branch: bzr merge lp:mir/0.17
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Mir development team Pending
Review via email: mp+276704@code.launchpad.net

Commit message

Mir 0.17.1 release

Description of the change

Mir 0.17.1 release

To post a comment you must log in.
lp:mir/0.17 updated
3017. By Alberto Aguirre

Avoid __attribute__((weak)) as that will fail to resolve symbols from
lazily loaded libraries (like Qt platform plugins apparently).

Cherry picked from lp:mir r3060

3018. By Alberto Aguirre

Update changelog

3019. By Brandon Schaefer

Add missing shlibs:Depends entry to libmircookie1 package dependency list

3020. By Alberto Aguirre

Update changelog, new bugfix entry

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:mir/0.17 updated
3021. By Alexandros Frantzis

input: Return an empty input region bounding rectangle when there are no outputs.

Cherry picked from lp:mir r3085

3022. By Alberto Aguirre

Update changelog

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-10-08 09:48:35 +0000
+++ CMakeLists.txt 2015-11-05 16:01:02 +0000
@@ -28,7 +28,7 @@
2828
29set(MIR_VERSION_MAJOR 0)29set(MIR_VERSION_MAJOR 0)
30set(MIR_VERSION_MINOR 17)30set(MIR_VERSION_MINOR 17)
31set(MIR_VERSION_PATCH 0)31set(MIR_VERSION_PATCH 1)
3232
33add_definitions(-DMIR_VERSION_MAJOR=${MIR_VERSION_MAJOR})33add_definitions(-DMIR_VERSION_MAJOR=${MIR_VERSION_MAJOR})
34add_definitions(-DMIR_VERSION_MINOR=${MIR_VERSION_MINOR})34add_definitions(-DMIR_VERSION_MINOR=${MIR_VERSION_MINOR})
3535
=== modified file 'debian/changelog'
--- debian/changelog 2015-10-08 16:12:19 +0000
+++ debian/changelog 2015-11-05 16:01:02 +0000
@@ -1,3 +1,23 @@
1mir (0.17.1) UNRELEASED; urgency=medium
2
3 * New upstream release 0.17.1 (https://launchpad.net/mir/+milestone/0.17.1)
4 - No ABI changes. Bug fix release only.
5 - Bugs fixed:
6 . compositing never stops when external monitor is connected
7 (LP: #1499039)
8 . half screen on external monitor (LP: #1511538)
9 . Nested servers don't apply their display configuration at startup
10 (LP: #1492269)
11 . libmircookie1 package does not list libnettle as dependency
12 (LP: #1513225)
13 . unity-system-compositor crash, no interaction on windowed mode
14 (LP: #1511095)
15 . mir_connection_get_egl_pixel_format() crashes (LP: #1510218)
16 . [regression] mir-client-platform-mesa-dev pkg-config file dropped
17 (LP: #1509005)
18
19 -- Alberto Aguirre <alberto.aguirre@canonical.com> Wed, 04 Nov 2015 15:08:54 -0600
20
1mir (0.17.0+15.10.20151008.2-0ubuntu1) wily; urgency=medium21mir (0.17.0+15.10.20151008.2-0ubuntu1) wily; urgency=medium
222
3 [ Alexandros Frantzis ]23 [ Alexandros Frantzis ]
424
=== modified file 'debian/control'
--- debian/control 2015-10-05 02:18:18 +0000
+++ debian/control 2015-11-05 16:01:02 +0000
@@ -424,6 +424,7 @@
424Multi-Arch: same424Multi-Arch: same
425Pre-Depends: ${misc:Pre-Depends}425Pre-Depends: ${misc:Pre-Depends}
426Depends: ${misc:Depends},426Depends: ${misc:Depends},
427 ${shlibs:Depends}
427Description: Produce and verify spoof-resistant timestamps - runtime library428Description: Produce and verify spoof-resistant timestamps - runtime library
428 libmircookie provides a simple mechanism for a group of cooperating processes429 libmircookie provides a simple mechanism for a group of cooperating processes
429 to hand out and verify difficult-to-forge timestamps to untrusted 3rd parties.430 to hand out and verify difficult-to-forge timestamps to untrusted 3rd parties.
430431
=== modified file 'debian/mir-client-platform-mesa-dev.install'
--- debian/mir-client-platform-mesa-dev.install 2015-09-24 22:30:09 +0000
+++ debian/mir-client-platform-mesa-dev.install 2015-11-05 16:01:02 +0000
@@ -1,2 +1,3 @@
1usr/include/mirplatform/mir_toolkit/mesa1usr/include/mirplatform/mir_toolkit/mesa
2usr/lib/*/pkgconfig/mir-client-platform-mesa-dev.pc
2usr/lib/*/pkgconfig/mir-client-platform-mesa.pc3usr/lib/*/pkgconfig/mir-client-platform-mesa.pc
34
=== modified file 'include/platform/mir/graphics/display_configuration.h'
--- include/platform/mir/graphics/display_configuration.h 2015-10-05 05:22:49 +0000
+++ include/platform/mir/graphics/display_configuration.h 2015-11-05 16:01:02 +0000
@@ -181,6 +181,9 @@
181 DisplayConfiguration& operator=(DisplayConfiguration const& c) = delete;181 DisplayConfiguration& operator=(DisplayConfiguration const& c) = delete;
182};182};
183183
184bool operator==(DisplayConfiguration const& lhs, DisplayConfiguration const& rhs);
185bool operator!=(DisplayConfiguration const& lhs, DisplayConfiguration const& rhs);
186
184std::ostream& operator<<(std::ostream& out, DisplayConfiguration const& val);187std::ostream& operator<<(std::ostream& out, DisplayConfiguration const& val);
185188
186}189}
187190
=== modified file 'src/platform/graphics/display_configuration.cpp'
--- src/platform/graphics/display_configuration.cpp 2015-10-02 05:14:37 +0000
+++ src/platform/graphics/display_configuration.cpp 2015-11-05 16:01:02 +0000
@@ -145,6 +145,7 @@
145145
146 out << "\tscale: " << val.scale << std::endl;146 out << "\tscale: " << val.scale << std::endl;
147 out << "\tform factor: " << as_string(val.form_factor) << std::endl;147 out << "\tform factor: " << as_string(val.form_factor) << std::endl;
148 out << "\torientation: " << val.orientation << '\n';
148 out << "}" << std::endl;149 out << "}" << std::endl;
149150
150 return out;151 return out;
@@ -219,6 +220,28 @@
219 return !(val1 == val2);220 return !(val1 == val2);
220}221}
221222
223bool mg::operator==(DisplayConfiguration const& lhs, DisplayConfiguration const& rhs)
224{
225 std::vector<DisplayConfigurationCard> lhs_cards;
226 std::vector<DisplayConfigurationOutput> lhs_outputs;
227
228 lhs.for_each_card([&lhs_cards](DisplayConfigurationCard const& card) { lhs_cards.emplace_back(card); });
229 lhs.for_each_output([&lhs_outputs](DisplayConfigurationOutput const& output) { lhs_outputs.emplace_back(output); });
230
231 std::vector<DisplayConfigurationCard> rhs_cards;
232 std::vector<DisplayConfigurationOutput> rhs_outputs;
233
234 rhs.for_each_card([&rhs_cards](DisplayConfigurationCard const& card) { rhs_cards.emplace_back(card); });
235 rhs.for_each_output([&rhs_outputs](DisplayConfigurationOutput const& output) { rhs_outputs.emplace_back(output); });
236
237 return lhs_cards == rhs_cards && lhs_outputs == rhs_outputs;
238}
239
240bool mg::operator!=(DisplayConfiguration const& lhs, DisplayConfiguration const& rhs)
241{
242 return !(lhs == rhs);
243}
244
222namespace245namespace
223{246{
224mir::geometry::Rectangle extents_of(247mir::geometry::Rectangle extents_of(
225248
=== modified file 'src/platforms/android/client/android_client_platform.cpp'
--- src/platforms/android/client/android_client_platform.cpp 2015-07-21 04:30:03 +0000
+++ src/platforms/android/client/android_client_platform.cpp 2015-11-05 16:01:02 +0000
@@ -24,6 +24,7 @@
24#include "android_client_buffer_factory.h"24#include "android_client_buffer_factory.h"
25#include "egl_native_surface_interpreter.h"25#include "egl_native_surface_interpreter.h"
2626
27#include "mir/weak_egl.h"
27#include <EGL/egl.h>28#include <EGL/egl.h>
2829
29#include <boost/throw_exception.hpp>30#include <boost/throw_exception.hpp>
@@ -124,19 +125,6 @@
124 return buf->anwb();125 return buf->anwb();
125}126}
126127
127/*
128 * Driver modules get dlopened with RTLD_NOW, meaning that if the below egl
129 * functions aren't found in memory the driver fails to load. This would
130 * normally prevent software clients (those not linked to libEGL) from
131 * successfully loading our client module, but if we mark the undefined
132 * egl function symbols as "weak" then their absence is no longer an error,
133 * even with RTLD_NOW.
134 */
135extern "C" EGLAPI EGLBoolean EGLAPIENTRY
136 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
137 EGLint attribute, EGLint *value)
138 __attribute__((weak));
139
140MirPixelFormat mcla::AndroidClientPlatform::get_egl_pixel_format(128MirPixelFormat mcla::AndroidClientPlatform::get_egl_pixel_format(
141 EGLDisplay disp, EGLConfig conf) const129 EGLDisplay disp, EGLConfig conf) const
142{130{
@@ -144,7 +132,8 @@
144132
145 // EGL_KHR_platform_android says this will always work...133 // EGL_KHR_platform_android says this will always work...
146 EGLint vis = 0;134 EGLint vis = 0;
147 if (eglGetConfigAttrib(disp, conf, EGL_NATIVE_VISUAL_ID, &vis))135 mcl::WeakEGL weak;
136 if (weak.eglGetConfigAttrib(disp, conf, EGL_NATIVE_VISUAL_ID, &vis))
148 mir_format = mir::graphics::android::to_mir_format(vis);137 mir_format = mir::graphics::android::to_mir_format(vis);
149138
150 return mir_format;139 return mir_format;
151140
=== modified file 'src/platforms/common/client/mir/CMakeLists.txt'
--- src/platforms/common/client/mir/CMakeLists.txt 2015-01-19 14:16:46 +0000
+++ src/platforms/common/client/mir/CMakeLists.txt 2015-11-05 16:01:02 +0000
@@ -2,4 +2,5 @@
22
3add_library(client_platform_common OBJECT3add_library(client_platform_common OBJECT
4 aging_buffer.cpp4 aging_buffer.cpp
5 weak_egl.cpp
5)6)
67
=== added file 'src/platforms/common/client/mir/weak_egl.cpp'
--- src/platforms/common/client/mir/weak_egl.cpp 1970-01-01 00:00:00 +0000
+++ src/platforms/common/client/mir/weak_egl.cpp 2015-11-05 16:01:02 +0000
@@ -0,0 +1,65 @@
1/*
2 * EGL without any linkage requirements!
3 * ~~~
4 * Copyright © 2015 Canonical Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License version 3,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
19 */
20
21#include "weak_egl.h"
22#include <dlfcn.h>
23
24namespace mir { namespace client {
25
26WeakEGL::WeakEGL()
27 : egl1(nullptr)
28 , pGetConfigAttrib(nullptr)
29{
30}
31
32WeakEGL::~WeakEGL()
33{
34 if (egl1)
35 dlclose(egl1);
36}
37
38EGLBoolean WeakEGL::eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
39 EGLint attribute, EGLint* value)
40{
41 if (find("eglGetConfigAttrib", (void**)&pGetConfigAttrib))
42 return pGetConfigAttrib(dpy, config, attribute, value);
43 else
44 return EGL_FALSE;
45}
46
47bool WeakEGL::find(char const* name, void** func)
48{
49 if (!*func)
50 {
51 // RTLD_DEFAULT is first choice to support wrappers like MockEGL
52 if (!(*func = dlsym(RTLD_DEFAULT, name)))
53 {
54 // This will work more in real-world situations if the library
55 // is hidden behind an RTLD_LOCAL (e.g. a Qt plugin)
56 if (!egl1)
57 egl1 = dlopen("libEGL.so.1", RTLD_NOLOAD|RTLD_LAZY);
58 if (egl1)
59 *func = dlsym(egl1, name);
60 }
61 }
62 return *func != nullptr;
63}
64
65}} // namespace mir::client
066
=== added file 'src/platforms/common/client/mir/weak_egl.h'
--- src/platforms/common/client/mir/weak_egl.h 1970-01-01 00:00:00 +0000
+++ src/platforms/common/client/mir/weak_egl.h 2015-11-05 16:01:02 +0000
@@ -0,0 +1,47 @@
1/*
2 * EGL without any linkage requirements!
3 * ~~~
4 * Copyright © 2015 Canonical Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License version 3,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
19 */
20
21#ifndef MIR_CLIENT_WEAK_EGL_H_
22#define MIR_CLIENT_WEAK_EGL_H_
23
24#include <EGL/egl.h>
25#include <dlfcn.h>
26
27namespace mir { namespace client {
28
29class WeakEGL
30{
31public:
32 WeakEGL();
33 ~WeakEGL();
34 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
35 EGLint attribute, EGLint* value);
36
37private:
38 bool find(char const* name, void** func);
39
40 void* egl1;
41 EGLBoolean (*pGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
42 EGLint attribute, EGLint* value);
43};
44
45}} // namespace mir::client
46
47#endif // MIR_CLIENT_WEAK_EGL_H_
048
=== modified file 'src/platforms/mesa/CMakeLists.txt'
--- src/platforms/mesa/CMakeLists.txt 2015-09-24 22:30:09 +0000
+++ src/platforms/mesa/CMakeLists.txt 2015-11-05 16:01:02 +0000
@@ -1,6 +1,12 @@
1set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")1set(INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/include")
22
3configure_file(3configure_file(
4 ${CMAKE_CURRENT_SOURCE_DIR}/mir-client-platform-mesa-dev.pc.in
5 ${CMAKE_CURRENT_BINARY_DIR}/mir-client-platform-mesa-dev.pc
6 @ONLY
7)
8
9configure_file(
4 ${CMAKE_CURRENT_SOURCE_DIR}/mir-client-platform-mesa.pc.in10 ${CMAKE_CURRENT_SOURCE_DIR}/mir-client-platform-mesa.pc.in
5 ${CMAKE_CURRENT_BINARY_DIR}/mir-client-platform-mesa.pc11 ${CMAKE_CURRENT_BINARY_DIR}/mir-client-platform-mesa.pc
6 @ONLY12 @ONLY
@@ -20,6 +26,9 @@
20)26)
2127
22install(28install(
23 FILES ${CMAKE_CURRENT_BINARY_DIR}/mir-client-platform-mesa.pc29 FILES
30 ${CMAKE_CURRENT_BINARY_DIR}/mir-client-platform-mesa-dev.pc
31 ${CMAKE_CURRENT_BINARY_DIR}/mir-client-platform-mesa.pc
32
24 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig33 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
25)34)
2635
=== modified file 'src/platforms/mesa/client/client_platform.cpp'
--- src/platforms/mesa/client/client_platform.cpp 2015-07-17 08:08:44 +0000
+++ src/platforms/mesa/client/client_platform.cpp 2015-11-05 16:01:02 +0000
@@ -23,6 +23,7 @@
23#include "native_surface.h"23#include "native_surface.h"
24#include "mir/client_buffer_factory.h"24#include "mir/client_buffer_factory.h"
25#include "mir/client_context.h"25#include "mir/client_context.h"
26#include "mir/weak_egl.h"
26#include "mir_toolkit/mesa/platform_operation.h"27#include "mir_toolkit/mesa/platform_operation.h"
2728
28#include <cstring>29#include <cstring>
@@ -179,19 +180,6 @@
179}180}
180181
181182
182/*
183 * Driver modules get dlopened with RTLD_NOW, meaning that if the below egl
184 * functions aren't found in memory the driver fails to load. This would
185 * normally prevent software clients (those not linked to libEGL) from
186 * successfully loading our client module, but if we mark the undefined
187 * egl function symbols as "weak" then their absence is no longer an error,
188 * even with RTLD_NOW.
189 */
190extern "C" EGLAPI EGLBoolean EGLAPIENTRY
191 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
192 EGLint attribute, EGLint *value)
193 __attribute__((weak));
194
195MirPixelFormat mclm::ClientPlatform::get_egl_pixel_format(183MirPixelFormat mclm::ClientPlatform::get_egl_pixel_format(
196 EGLDisplay disp, EGLConfig conf) const184 EGLDisplay disp, EGLConfig conf) const
197{185{
@@ -208,10 +196,11 @@
208 * EGL_NATIVE_VISUAL_ID, so ignore that for now.196 * EGL_NATIVE_VISUAL_ID, so ignore that for now.
209 */197 */
210 EGLint r = 0, g = 0, b = 0, a = 0;198 EGLint r = 0, g = 0, b = 0, a = 0;
211 eglGetConfigAttrib(disp, conf, EGL_RED_SIZE, &r);199 mcl::WeakEGL weak;
212 eglGetConfigAttrib(disp, conf, EGL_GREEN_SIZE, &g);200 weak.eglGetConfigAttrib(disp, conf, EGL_RED_SIZE, &r);
213 eglGetConfigAttrib(disp, conf, EGL_BLUE_SIZE, &b);201 weak.eglGetConfigAttrib(disp, conf, EGL_GREEN_SIZE, &g);
214 eglGetConfigAttrib(disp, conf, EGL_ALPHA_SIZE, &a);202 weak.eglGetConfigAttrib(disp, conf, EGL_BLUE_SIZE, &b);
203 weak.eglGetConfigAttrib(disp, conf, EGL_ALPHA_SIZE, &a);
215204
216 if (r == 8 && g == 8 && b == 8)205 if (r == 8 && g == 8 && b == 8)
217 {206 {
218207
=== renamed file 'src/platforms/mesa/mir-client-platform-mesa.pc.in' => 'src/platforms/mesa/mir-client-platform-mesa-dev.pc.in'
--- src/platforms/mesa/mir-client-platform-mesa.pc.in 2015-10-07 12:53:33 +0000
+++ src/platforms/mesa/mir-client-platform-mesa-dev.pc.in 2015-11-05 16:01:02 +0000
@@ -1,6 +1,6 @@
1includedir=@INCLUDEDIR@/mirplatform1includedir=@INCLUDEDIR@/mirplatform
22
3Name: mir-client-platform-mesa3Name: mir-client-platform-mesa-dev
4Description: Mir Mesa client platform development files4Description: Mir Mesa client platform development files
5Version: @MIR_VERSION@5Version: @MIR_VERSION@
6Requires.private: mirclient6Requires.private: mirclient
77
=== added file 'src/platforms/mesa/mir-client-platform-mesa.pc.in'
--- src/platforms/mesa/mir-client-platform-mesa.pc.in 1970-01-01 00:00:00 +0000
+++ src/platforms/mesa/mir-client-platform-mesa.pc.in 2015-11-05 16:01:02 +0000
@@ -0,0 +1,7 @@
1includedir=@INCLUDEDIR@/mirplatform
2
3Name: mir-client-platform-mesa
4Description: Mir Mesa client platform development files
5Version: @MIR_VERSION@
6Requires.private: mirclient
7Cflags: -I${includedir}
08
=== modified file 'src/server/graphics/nested/display.cpp'
--- src/server/graphics/nested/display.cpp 2015-10-06 09:28:48 +0000
+++ src/server/graphics/nested/display.cpp 2015-11-05 16:01:02 +0000
@@ -29,6 +29,9 @@
29#include "mir/graphics/overlapping_output_grouping.h"29#include "mir/graphics/overlapping_output_grouping.h"
30#include "mir/graphics/gl_config.h"30#include "mir/graphics/gl_config.h"
31#include "mir/graphics/egl_error.h"31#include "mir/graphics/egl_error.h"
32#include "mir_toolkit/mir_blob.h"
33#include "mir_toolkit/mir_connection.h"
34#include "mir/raii.h"
3235
33#include <boost/throw_exception.hpp>36#include <boost/throw_exception.hpp>
34#include <stdexcept>37#include <stdexcept>
@@ -145,6 +148,20 @@
145 return std::chrono::milliseconds::zero();148 return std::chrono::milliseconds::zero();
146}149}
147150
151namespace
152{
153auto copy_config(MirDisplayConfiguration* conf) -> std::shared_ptr<MirDisplayConfiguration>
154{
155 auto const blob = mir::raii::deleter_for(
156 mir_blob_from_display_configuration(conf),
157 [] (MirBlob* b) { mir_blob_release(b); });
158
159 return std::shared_ptr<MirDisplayConfiguration>{
160 mir_blob_to_display_configuration(blob.get()),
161 [] (MirDisplayConfiguration* c) { if (c) mir_display_config_destroy(c); }};
162}
163}
164
148mgn::Display::Display(165mgn::Display::Display(
149 std::shared_ptr<mg::Platform> const& platform,166 std::shared_ptr<mg::Platform> const& platform,
150 std::shared_ptr<HostConnection> const& connection,167 std::shared_ptr<HostConnection> const& connection,
@@ -159,10 +176,15 @@
159 display_report{display_report},176 display_report{display_report},
160 egl_display{connection->egl_native_display(), gl_config},177 egl_display{connection->egl_native_display(), gl_config},
161 cursor_listener{cursor_listener},178 cursor_listener{cursor_listener},
162 outputs{}179 outputs{},
180 current_configuration(std::make_unique<NestedDisplayConfiguration>(connection->create_display_config()))
163{181{
164 std::shared_ptr<DisplayConfiguration> conf(configuration());182 std::shared_ptr<DisplayConfiguration> conf(configuration());
165 initial_conf_policy->apply_to(*conf);183 initial_conf_policy->apply_to(*conf);
184
185 if (*current_configuration != *conf)
186 apply_to_connection(*conf);
187
166 create_surfaces(*conf);188 create_surfaces(*conf);
167}189}
168190
@@ -181,8 +203,8 @@
181203
182std::unique_ptr<mg::DisplayConfiguration> mgn::Display::configuration() const204std::unique_ptr<mg::DisplayConfiguration> mgn::Display::configuration() const
183{205{
184 return std::make_unique<NestedDisplayConfiguration>(206 std::lock_guard<std::mutex> lock(configuration_mutex);
185 connection->create_display_config());207 return std::make_unique<NestedDisplayConfiguration>(copy_config(*current_configuration));
186}208}
187209
188void mgn::Display::complete_display_initialization(MirPixelFormat format)210void mgn::Display::complete_display_initialization(MirPixelFormat format)
@@ -195,8 +217,12 @@
195217
196void mgn::Display::configure(mg::DisplayConfiguration const& configuration)218void mgn::Display::configure(mg::DisplayConfiguration const& configuration)
197{219{
198 create_surfaces(configuration);220 std::lock_guard<std::mutex> lock(configuration_mutex);
199 apply_to_connection(configuration);221 if (*current_configuration != configuration)
222 {
223 apply_to_connection(configuration);
224 create_surfaces(configuration);
225 }
200}226}
201227
202void mgn::Display::create_surfaces(mg::DisplayConfiguration const& configuration)228void mgn::Display::create_surfaces(mg::DisplayConfiguration const& configuration)
@@ -254,13 +280,20 @@
254 auto const& conf = dynamic_cast<NestedDisplayConfiguration const&>(configuration);280 auto const& conf = dynamic_cast<NestedDisplayConfiguration const&>(configuration);
255281
256 connection->apply_display_config(*conf);282 connection->apply_display_config(*conf);
283
284 current_configuration = std::make_unique<NestedDisplayConfiguration>(copy_config(conf));
257}285}
258286
259void mgn::Display::register_configuration_change_handler(287void mgn::Display::register_configuration_change_handler(
260 EventHandlerRegister& /*handlers*/,288 EventHandlerRegister& /*handlers*/,
261 DisplayConfigurationChangeHandler const& conf_change_handler)289 DisplayConfigurationChangeHandler const& conf_change_handler)
262{290{
263 connection->set_display_config_change_callback(conf_change_handler);291 auto const handler = [this, conf_change_handler] {
292 current_configuration = std::make_unique<NestedDisplayConfiguration>(connection->create_display_config());
293 conf_change_handler();
294 };
295
296 connection->set_display_config_change_callback(handler);
264}297}
265298
266void mgn::Display::register_pause_resume_handlers(299void mgn::Display::register_pause_resume_handlers(
267300
=== modified file 'src/server/graphics/nested/display.h'
--- src/server/graphics/nested/display.h 2015-08-20 02:44:54 +0000
+++ src/server/graphics/nested/display.h 2015-11-05 16:01:02 +0000
@@ -52,6 +52,8 @@
5252
53namespace nested53namespace nested
54{54{
55class NestedDisplayConfiguration;
56
55namespace detail57namespace detail
56{58{
5759
@@ -151,6 +153,10 @@
151153
152 std::mutex outputs_mutex;154 std::mutex outputs_mutex;
153 std::unordered_map<DisplayConfigurationOutputId, std::shared_ptr<detail::DisplaySyncGroup>> outputs;155 std::unordered_map<DisplayConfigurationOutputId, std::shared_ptr<detail::DisplaySyncGroup>> outputs;
156
157 std::mutex mutable configuration_mutex;
158 std::unique_ptr<NestedDisplayConfiguration> current_configuration;
159
154 void create_surfaces(mir::graphics::DisplayConfiguration const& configuration);160 void create_surfaces(mir::graphics::DisplayConfiguration const& configuration);
155 void apply_to_connection(mir::graphics::DisplayConfiguration const& configuration);161 void apply_to_connection(mir::graphics::DisplayConfiguration const& configuration);
156 void complete_display_initialization(MirPixelFormat format);162 void complete_display_initialization(MirPixelFormat format);
157163
=== modified file 'src/server/input/display_input_region.cpp'
--- src/server/input/display_input_region.cpp 2015-09-24 02:16:12 +0000
+++ src/server/input/display_input_region.cpp 2015-11-05 16:01:02 +0000
@@ -51,7 +51,10 @@
51 // to group a touchscreen with a display. So for now, just return the view area51 // to group a touchscreen with a display. So for now, just return the view area
52 // of the first display, as that matches the most common systems (laptops with touchscreens,52 // of the first display, as that matches the most common systems (laptops with touchscreens,
53 // phone/tablets with touchscreens).53 // phone/tablets with touchscreens).
54 return *rectangles.begin();54 if (rectangles.size() != 0)
55 return *rectangles.begin();
56 else
57 return geom::Rectangle{};
55}58}
5659
57void mi::DisplayInputRegion::confine(geom::Point& point)60void mi::DisplayInputRegion::confine(geom::Point& point)
5861
=== modified file 'src/server/scene/rendering_tracker.cpp'
--- src/server/scene/rendering_tracker.cpp 2015-02-22 07:46:25 +0000
+++ src/server/scene/rendering_tracker.cpp 2015-11-05 16:01:02 +0000
@@ -68,6 +68,18 @@
68 configure_visibility(mir_surface_visibility_occluded);68 configure_visibility(mir_surface_visibility_occluded);
69}69}
7070
71bool ms::RenderingTracker::is_exposed_in(mc::CompositorID cid) const
72{
73 std::lock_guard<std::mutex> lock{guard};
74
75 ensure_is_active_compositor(cid);
76
77 if (occlusions.size() == 0)
78 return true;
79
80 return occlusions.find(cid) == occlusions.end();
81}
82
71bool ms::RenderingTracker::occluded_in_all_active_compositors()83bool ms::RenderingTracker::occluded_in_all_active_compositors()
72{84{
73 return occlusions == active_compositors_;85 return occlusions == active_compositors_;
7486
=== modified file 'src/server/scene/rendering_tracker.h'
--- src/server/scene/rendering_tracker.h 2015-02-22 07:46:25 +0000
+++ src/server/scene/rendering_tracker.h 2015-11-05 16:01:02 +0000
@@ -42,6 +42,7 @@
42 void rendered_in(compositor::CompositorID cid);42 void rendered_in(compositor::CompositorID cid);
43 void occluded_in(compositor::CompositorID cid);43 void occluded_in(compositor::CompositorID cid);
44 void active_compositors(std::set<compositor::CompositorID> const& cids);44 void active_compositors(std::set<compositor::CompositorID> const& cids);
45 bool is_exposed_in(compositor::CompositorID cid) const;
4546
46private:47private:
47 bool occluded_in_all_active_compositors();48 bool occluded_in_all_active_compositors();
@@ -52,7 +53,7 @@
52 std::weak_ptr<Surface> const weak_surface;53 std::weak_ptr<Surface> const weak_surface;
53 std::set<compositor::CompositorID> occlusions;54 std::set<compositor::CompositorID> occlusions;
54 std::set<compositor::CompositorID> active_compositors_;55 std::set<compositor::CompositorID> active_compositors_;
55 std::mutex guard;56 std::mutex mutable guard;
56};57};
5758
58}59}
5960
=== modified file 'src/server/scene/surface_stack.cpp'
--- src/server/scene/surface_stack.cpp 2015-06-18 02:46:16 +0000
+++ src/server/scene/surface_stack.cpp 2015-11-05 16:01:02 +0000
@@ -168,15 +168,18 @@
168 // TODO: Rename mir_surface_attrib_visibility as it's obviously168 // TODO: Rename mir_surface_attrib_visibility as it's obviously
169 // confusing with visible()169 // confusing with visible()
170 if (surface->visible() &&170 if (surface->visible() &&
171 surface->query(mir_surface_attrib_visibility) ==171 surface->query(mir_surface_attrib_visibility) == mir_surface_visibility_exposed)
172 mir_surface_visibility_exposed)
173 {172 {
174 // Note that we ask the surface and not a Renderable.173 auto const tracker = rendering_trackers.find(surface.get());
175 // This is because we don't want to waste time and resources174 if (tracker != rendering_trackers.end() && tracker->second->is_exposed_in(id))
176 // on a snapshot till we're sure we need it...175 {
177 int ready = surface->buffers_ready_for_compositor(id);176 // Note that we ask the surface and not a Renderable.
178 if (ready > result)177 // This is because we don't want to waste time and resources
179 result = ready;178 // on a snapshot till we're sure we need it...
179 int ready = surface->buffers_ready_for_compositor(id);
180 if (ready > result)
181 result = ready;
182 }
180 }183 }
181 }184 }
182 }185 }
183186
=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
--- tests/acceptance-tests/test_nested_mir.cpp 2015-10-07 17:08:36 +0000
+++ tests/acceptance-tests/test_nested_mir.cpp 2015-11-05 16:01:02 +0000
@@ -22,12 +22,14 @@
22#include "mir/input/cursor_images.h"22#include "mir/input/cursor_images.h"
23#include "mir/graphics/display.h"23#include "mir/graphics/display.h"
24#include "mir/graphics/display_configuration.h"24#include "mir/graphics/display_configuration.h"
25#include "mir/graphics/display_configuration_policy.h"
25#include "mir/graphics/display_configuration_report.h"26#include "mir/graphics/display_configuration_report.h"
26#include "mir/input/cursor_listener.h"27#include "mir/input/cursor_listener.h"
27#include "mir/cached_ptr.h"28#include "mir/cached_ptr.h"
28#include "mir/main_loop.h"29#include "mir/main_loop.h"
29#include "mir/scene/session_coordinator.h"30#include "mir/scene/session_coordinator.h"
30#include "mir/scene/session.h"31#include "mir/scene/session.h"
32#include "mir/shell/display_configuration_controller.h"
31#include "mir/shell/host_lifecycle_event_listener.h"33#include "mir/shell/host_lifecycle_event_listener.h"
3234
33#include "mir_test_framework/headless_in_process_server.h"35#include "mir_test_framework/headless_in_process_server.h"
@@ -183,10 +185,41 @@
183 bool hidden{false};185 bool hidden{false};
184};186};
185187
188struct MockDisplayConfigurationPolicy : mg::DisplayConfigurationPolicy
189{
190 MOCK_METHOD1(apply_to, void (mg::DisplayConfiguration&));
191};
192
186class NestedMirRunner : public mtf::HeadlessNestedServerRunner193class NestedMirRunner : public mtf::HeadlessNestedServerRunner
187{194{
188public:195public:
189 NestedMirRunner(std::string const& connection_string)196 NestedMirRunner(std::string const& connection_string)
197 : NestedMirRunner(connection_string, true)
198 {
199 start_server();
200 }
201
202 virtual ~NestedMirRunner()
203 {
204 stop_server();
205 }
206
207 std::shared_ptr<MockHostLifecycleEventListener> the_mock_host_lifecycle_event_listener()
208 {
209 return mock_host_lifecycle_event_listener([]
210 { return std::make_shared<NiceMock<MockHostLifecycleEventListener>>(); });
211 }
212
213 std::shared_ptr<CursorWrapper> cursor_wrapper;
214
215 virtual std::shared_ptr<MockDisplayConfigurationPolicy> mock_display_configuration_policy()
216 {
217 return mock_display_configuration_policy_([this]
218 { return std::make_shared<NiceMock<MockDisplayConfigurationPolicy>>(); });
219 }
220
221protected:
222 NestedMirRunner(std::string const& connection_string, bool)
190 : mtf::HeadlessNestedServerRunner(connection_string)223 : mtf::HeadlessNestedServerRunner(connection_string)
191 {224 {
192 server.override_the_host_lifecycle_event_listener([this]225 server.override_the_host_lifecycle_event_listener([this]
@@ -197,24 +230,15 @@
197230
198 server.override_the_cursor_images([] { return std::make_shared<CursorImages>(); });231 server.override_the_cursor_images([] { return std::make_shared<CursorImages>(); });
199232
200 start_server();233 server.wrap_display_configuration_policy([this]
201 }234 (std::shared_ptr<mg::DisplayConfigurationPolicy> const&)
202235 { return mock_display_configuration_policy(); });
203 ~NestedMirRunner()236 }
204 {
205 stop_server();
206 }
207
208 std::shared_ptr<MockHostLifecycleEventListener> the_mock_host_lifecycle_event_listener()
209 {
210 return mock_host_lifecycle_event_listener([]
211 { return std::make_shared<NiceMock<MockHostLifecycleEventListener>>(); });
212 }
213
214 std::shared_ptr<CursorWrapper> cursor_wrapper;
215237
216private:238private:
217 mir::CachedPtr<MockHostLifecycleEventListener> mock_host_lifecycle_event_listener;239 mir::CachedPtr<MockHostLifecycleEventListener> mock_host_lifecycle_event_listener;
240
241 mir::CachedPtr<MockDisplayConfigurationPolicy> mock_display_configuration_policy_;
218};242};
219243
220struct NestedServer : mtf::HeadlessInProcessServer244struct NestedServer : mtf::HeadlessInProcessServer
@@ -376,6 +400,7 @@
376 // No post on surface creation400 // No post on surface creation
377 EXPECT_CALL(*mock_session_mediator_report, session_submit_buffer_called(_)).Times(0);401 EXPECT_CALL(*mock_session_mediator_report, session_submit_buffer_called(_)).Times(0);
378 NestedMirRunner nested_mir{new_connection()};402 NestedMirRunner nested_mir{new_connection()};
403
379 auto const connection = mir_connect_sync(nested_mir.new_connection().c_str(), __PRETTY_FUNCTION__);404 auto const connection = mir_connect_sync(nested_mir.new_connection().c_str(), __PRETTY_FUNCTION__);
380 auto const surface = mtf::make_any_surface(connection);405 auto const surface = mtf::make_any_surface(connection);
381406
@@ -692,3 +717,72 @@
692 // surface as the host cursor then reverts to default.717 // surface as the host cursor then reverts to default.
693 Mock::VerifyAndClearExpectations(mock_cursor.get());718 Mock::VerifyAndClearExpectations(mock_cursor.get());
694}719}
720
721TEST_F(NestedServer, applies_display_config_on_startup)
722{
723 mt::WaitCondition condition;
724
725 auto const expected_config = server.the_display()->configuration();
726 expected_config->for_each_output([](mg::UserDisplayConfigurationOutput& output)
727 { output.orientation = mir_orientation_inverted;});
728
729 EXPECT_CALL(*the_mock_display_configuration_report(), new_configuration(mt::DisplayConfigMatches(std::ref(*expected_config))))
730 .WillRepeatedly(InvokeWithoutArgs([&] { condition.wake_up_everyone(); }));
731
732 struct MyNestedMirRunner : NestedMirRunner
733 {
734 MyNestedMirRunner(std::string const& connection_string) :
735 NestedMirRunner(connection_string, true)
736 {
737 start_server();
738 }
739
740 std::shared_ptr<MockDisplayConfigurationPolicy> mock_display_configuration_policy() override
741 {
742 auto result = std::make_unique<MockDisplayConfigurationPolicy>();
743 EXPECT_CALL(*result, apply_to(_)).Times(AnyNumber())
744 .WillOnce(Invoke([](mg::DisplayConfiguration& config)
745 {
746 config.for_each_output([](mg::UserDisplayConfigurationOutput& output)
747 { output.orientation = mir_orientation_inverted; });
748 }));
749
750 return std::shared_ptr<MockDisplayConfigurationPolicy>(std::move(result));
751 }
752 } nested_mir{new_connection()};
753
754 auto const connection = mir_connect_sync(nested_mir.new_connection().c_str(), __PRETTY_FUNCTION__);
755 auto const surface = make_and_paint_surface(connection);
756
757 condition.wait_for_at_most_seconds(1);
758 Mock::VerifyAndClearExpectations(the_mock_display_configuration_report().get());
759
760 EXPECT_TRUE(condition.woken());
761
762 mir_surface_release_sync(surface);
763 mir_connection_release(connection);
764}
765
766TEST_F(NestedServer, base_configuration_change_in_host_is_seen_in_nested)
767{
768 NestedMirRunner nested_mir{new_connection()};
769 auto const connection = mir_connect_sync(nested_mir.new_connection().c_str(), __PRETTY_FUNCTION__);
770 auto const surface = make_and_paint_surface(connection);
771 auto const config_policy = nested_mir.mock_display_configuration_policy();
772 std::shared_ptr<mg::DisplayConfiguration> const new_config{server.the_display()->configuration()};
773 new_config->for_each_output([](mg::UserDisplayConfigurationOutput& output)
774 { output.orientation = mir_orientation_inverted;});
775
776 mt::WaitCondition condition;
777 EXPECT_CALL(*config_policy, apply_to(mt::DisplayConfigMatches(std::ref(*new_config))))
778 .WillOnce(InvokeWithoutArgs([&] { condition.wake_up_everyone(); }));
779
780 server.the_display_configuration_controller()->set_default_display_configuration(new_config);
781
782 condition.wait_for_at_most_seconds(1);
783 Mock::VerifyAndClearExpectations(config_policy.get());
784 EXPECT_TRUE(condition.woken());
785
786 mir_surface_release_sync(surface);
787 mir_connection_release(connection);
788}
695789
=== modified file 'tests/unit-tests/input/test_display_input_region.cpp'
--- tests/unit-tests/input/test_display_input_region.cpp 2015-09-24 02:16:12 +0000
+++ tests/unit-tests/input/test_display_input_region.cpp 2015-11-05 16:01:02 +0000
@@ -80,3 +80,14 @@
80 }80 }
8181
82}82}
83
84TEST(DisplayInputRegionTest, returns_empty_bounding_rectangle_when_there_are_no_outputs)
85{
86 geom::Rectangle const empty_rect{};
87 auto const stub_display = std::make_shared<mtd::StubDisplay>(0);
88
89 mi::DisplayInputRegion input_region{stub_display};
90
91 auto const bounding_rect = input_region.bounding_rectangle();
92 EXPECT_EQ(empty_rect, bounding_rect);
93}
8394
=== modified file 'tests/unit-tests/scene/test_surface_stack.cpp'
--- tests/unit-tests/scene/test_surface_stack.cpp 2015-06-26 08:00:59 +0000
+++ tests/unit-tests/scene/test_surface_stack.cpp 2015-11-05 16:01:02 +0000
@@ -339,6 +339,7 @@
339{339{
340 using namespace testing;340 using namespace testing;
341 ms::SurfaceStack stack{report};341 ms::SurfaceStack stack{report};
342 stack.register_compositor(this);
342 mtd::StubBuffer stub_buffer;343 mtd::StubBuffer stub_buffer;
343 int ready = 0;344 int ready = 0;
344 auto mock_queue = std::make_shared<testing::NiceMock<mtd::MockBufferBundle>>();345 auto mock_queue = std::make_shared<testing::NiceMock<mtd::MockBufferBundle>>();
@@ -384,6 +385,7 @@
384 using namespace testing;385 using namespace testing;
385386
386 ms::SurfaceStack stack{report};387 ms::SurfaceStack stack{report};
388 stack.register_compositor(this);
387 auto surface = std::make_shared<ms::BasicSurface>(389 auto surface = std::make_shared<ms::BasicSurface>(
388 std::string("stub"),390 std::string("stub"),
389 geom::Rectangle{{},{}},391 geom::Rectangle{{},{}},
@@ -405,6 +407,48 @@
405 EXPECT_EQ(0, stack.frames_pending(this));407 EXPECT_EQ(0, stack.frames_pending(this));
406}408}
407409
410TEST_F(SurfaceStack, scene_doesnt_count_pending_frames_from_partially_exposed_surfaces)
411{ // Regression test for LP: #1499039
412 using namespace testing;
413
414 // Partially exposed means occluded in one compositor but not another
415 ms::SurfaceStack stack{report};
416 auto const comp1 = reinterpret_cast<mc::CompositorID>(0);
417 auto const comp2 = reinterpret_cast<mc::CompositorID>(1);
418
419 stack.register_compositor(comp1);
420 stack.register_compositor(comp2);
421 auto surface = std::make_shared<ms::BasicSurface>(
422 std::string("stub"),
423 geom::Rectangle{{},{}},
424 false,
425 std::make_shared<mtd::StubBufferStream>(),
426 std::shared_ptr<mir::input::InputChannel>(),
427 std::shared_ptr<mir::input::InputSender>(),
428 std::shared_ptr<mg::CursorImage>(),
429 report);
430
431 stack.add_surface(surface, default_params.depth, default_params.input_mode);
432 post_a_frame(*surface);
433 post_a_frame(*surface);
434 post_a_frame(*surface);
435
436 EXPECT_EQ(3, stack.frames_pending(comp2));
437 auto elements = stack.scene_elements_for(comp1);
438 for (auto const& elem : elements)
439 {
440 elem->rendered();
441 }
442
443 elements = stack.scene_elements_for(comp2);
444 for (auto const& elem : elements)
445 {
446 elem->occluded();
447 }
448
449 EXPECT_EQ(0, stack.frames_pending(comp2));
450}
451
408TEST_F(SurfaceStack, surfaces_are_emitted_by_layer)452TEST_F(SurfaceStack, surfaces_are_emitted_by_layer)
409{453{
410 using namespace testing;454 using namespace testing;

Subscribers

People subscribed via source and target branches

to all changes: