Mir

Merge lp:~mir-team/mir/trunk-0.1.5 into lp:mir/0.1

Proposed by kevin gunn on 2014-02-07
Status: Merged
Merged at revision: 1175
Proposed branch: lp:~mir-team/mir/trunk-0.1.5
Merge into: lp:mir/0.1
Diff against target: 5417 lines (+1934/-662)
121 files modified
CMakeLists.txt (+1/-1)
debian/changelog (+49/-0)
debian/control (+4/-4)
debian/libmirclient7.install (+1/-1)
debian/libmirserver15.install (+1/-1)
debian/mir-utils.install (+1/-0)
examples/demo-inprocess-surface-client/inprocess_egl_client.cpp (+4/-2)
examples/render_surfaces.cpp (+3/-2)
include/platform/mir/graphics/display.h (+2/-2)
include/server/mir/compositor/buffer_stream.h (+1/-1)
include/server/mir/default_server_configuration.h (+3/-0)
include/server/mir/frontend/message_processor.h (+15/-1)
include/server/mir/frontend/screencast.h (+55/-0)
include/server/mir/frontend/shell.h (+8/-2)
include/server/mir/frontend/surface.h (+8/-1)
include/server/mir/frontend/template_protobuf_message_processor.h (+1/-3)
include/server/mir/shell/session.h (+6/-5)
include/shared/mir/int_wrapper.h (+16/-18)
include/test/mir_test_doubles/mock_buffer_bundle.h (+1/-1)
include/test/mir_test_doubles/mock_buffer_stream.h (+1/-1)
include/test/mir_test_doubles/mock_display.h (+1/-1)
include/test/mir_test_doubles/mock_fb_hal_device.h (+1/-3)
include/test/mir_test_doubles/mock_frontend_surface.h (+1/-1)
include/test/mir_test_doubles/mock_hwc_composer_device_1.h (+9/-1)
include/test/mir_test_doubles/mock_screencast.h (+50/-0)
include/test/mir_test_doubles/mock_shell.h (+6/-3)
include/test/mir_test_doubles/mock_shell_session.h (+2/-1)
include/test/mir_test_doubles/null_display.h (+4/-2)
include/test/mir_test_doubles/null_screencast.h (+52/-0)
include/test/mir_test_doubles/stub_buffer_stream.h (+2/-2)
include/test/mir_test_doubles/stub_display_configuration.h (+7/-0)
include/test/mir_test_doubles/stub_ipc_factory.h (+2/-2)
include/test/mir_test_doubles/stub_shell.h (+1/-1)
include/test/mir_test_doubles/stub_shell_session.h (+6/-1)
src/client/CMakeLists.txt (+2/-2)
src/client/mir_screencast.cpp (+13/-3)
src/client/mir_screencast.h (+1/-0)
src/client/mir_screencast_api.cpp (+15/-8)
src/client/rpc/mir_socket_rpc_channel.cpp (+7/-0)
src/platform/graphics/android/android_alloc_adaptor.cpp (+1/-1)
src/platform/graphics/android/android_display.cpp (+4/-2)
src/platform/graphics/android/android_display.h (+2/-2)
src/platform/graphics/android/android_platform.cpp (+1/-3)
src/platform/graphics/android/display_buffer.h (+0/-1)
src/platform/graphics/android/hwc_device.cpp (+4/-7)
src/platform/graphics/android/hwc_device.h (+2/-5)
src/platform/graphics/android/hwc_layers.cpp (+6/-2)
src/platform/graphics/android/internal_client_window.cpp (+6/-1)
src/platform/graphics/android/output_builder.cpp (+8/-12)
src/platform/graphics/android/output_builder.h (+1/-2)
src/platform/graphics/android/resource_factory.cpp (+3/-1)
src/platform/graphics/android/server_render_window.cpp (+6/-1)
src/platform/graphics/mesa/display.cpp (+4/-2)
src/platform/graphics/mesa/display.h (+4/-4)
src/server/CMakeLists.txt (+1/-1)
src/server/compositor/buffer_bundle.h (+1/-1)
src/server/compositor/buffer_stream_surfaces.cpp (+5/-4)
src/server/compositor/buffer_stream_surfaces.h (+1/-1)
src/server/compositor/default_configuration.cpp (+32/-0)
src/server/compositor/switching_bundle.cpp (+2/-2)
src/server/compositor/switching_bundle.h (+1/-1)
src/server/display_server.cpp (+5/-2)
src/server/frontend/default_configuration.cpp (+15/-6)
src/server/frontend/protobuf_ipc_factory.h (+7/-2)
src/server/frontend/protobuf_message_processor.cpp (+81/-5)
src/server/frontend/protobuf_message_processor.h (+3/-1)
src/server/frontend/protobuf_session_creator.cpp (+2/-2)
src/server/frontend/session_mediator.cpp (+144/-81)
src/server/frontend/session_mediator.h (+24/-3)
src/server/frontend/surface.cpp (+25/-1)
src/server/graphics/nested/nested_display.cpp (+6/-2)
src/server/graphics/nested/nested_display.h (+1/-1)
src/server/graphics/offscreen/display.cpp (+4/-2)
src/server/graphics/offscreen/display.h (+3/-3)
src/server/scene/application_session.cpp (+8/-1)
src/server/scene/application_session.h (+4/-1)
src/server/scene/basic_surface.cpp (+3/-3)
src/server/scene/basic_surface.h (+1/-1)
src/server/scene/session_manager.cpp (+6/-4)
src/server/scene/session_manager.h (+5/-2)
src/server/scene/surface_impl.cpp (+2/-2)
src/server/scene/surface_impl.h (+1/-1)
src/utils/CMakeLists.txt (+9/-0)
src/utils/screencast.cpp (+313/-0)
tests/acceptance-tests/test_client_screencast.cpp (+45/-133)
tests/acceptance-tests/test_display_configuration.cpp (+6/-4)
tests/acceptance-tests/test_protobuf.cpp (+1/-1)
tests/acceptance-tests/test_surfaces_with_output_id.cpp (+4/-2)
tests/draw/android_graphics.cpp (+0/-22)
tests/integration-tests/client/CMakeLists.txt (+6/-1)
tests/integration-tests/client/test_screencast.cpp (+191/-0)
tests/integration-tests/compositor/test_buffer_stream.cpp (+47/-21)
tests/integration-tests/compositor/test_swapping_swappers.cpp (+27/-2)
tests/integration-tests/graphics/android/test_buffer_integration.cpp (+25/-1)
tests/integration-tests/graphics/android/test_display_integration.cpp (+12/-37)
tests/integration-tests/graphics/android/test_internal_client.cpp (+3/-2)
tests/integration-tests/test_display_server_main_loop_events.cpp (+4/-2)
tests/integration-tests/test_session.cpp (+3/-2)
tests/integration-tests/test_session_manager.cpp (+6/-6)
tests/integration-tests/test_swapinterval.cpp (+15/-7)
tests/mir_test_framework/stubbed_server_configuration.cpp (+5/-3)
tests/unit-tests/client/test_mir_screencast.cpp (+52/-2)
tests/unit-tests/compositor/test_buffer_stream.cpp (+39/-9)
tests/unit-tests/compositor/test_switching_bundle.cpp (+58/-30)
tests/unit-tests/compositor/test_temporary_buffers.cpp (+2/-2)
tests/unit-tests/frontend/test_session_mediator.cpp (+67/-14)
tests/unit-tests/frontend/test_session_mediator_android.cpp (+3/-2)
tests/unit-tests/frontend/test_session_mediator_mesa.cpp (+4/-3)
tests/unit-tests/frontend/test_socket_session.cpp (+1/-1)
tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp (+1/-1)
tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp (+14/-7)
tests/unit-tests/graphics/android/test_hwc_common_device.cpp (+3/-1)
tests/unit-tests/graphics/android/test_hwc_device.cpp (+25/-7)
tests/unit-tests/graphics/android/test_output_builder.cpp (+7/-7)
tests/unit-tests/graphics/mesa/test_display_configuration.cpp (+2/-2)
tests/unit-tests/scene/test_application_session.cpp (+91/-34)
tests/unit-tests/scene/test_session_manager.cpp (+8/-8)
tests/unit-tests/scene/test_surface.cpp (+19/-20)
tests/unit-tests/scene/test_surface_impl.cpp (+2/-1)
tests/unit-tests/scene/test_surface_stack.cpp (+1/-1)
tests/unit-tests/shell/test_graphics_display_layout.cpp (+5/-5)
To merge this branch: bzr merge lp:~mir-team/mir/trunk-0.1.5
Reviewer Review Type Date Requested Status
kevin gunn (community) Approve on 2014-02-11
PS Jenkins bot (community) continuous-integration Approve on 2014-02-10
Daniel van Vugt 2014-02-07 Approve on 2014-02-10
Review via email: mp+205432@code.launchpad.net

Commit message

Latest upstream release of Mir0.1.5 (lp:~mir-team/mir/development-branch r1377)
plus upcoming enhancement:
   https://code.launchpad.net/~alan-griffiths/mir/fix-1276704/+merge/205357

Description of the change

.

To post a comment you must log in.
Daniel van Vugt (vanvugt) wrote :

I figured out what this branch is composed of and it's not r1372...

1. Start with dev r1377, but there's still about 1000 lines different.
2. Manually patch in https://code.launchpad.net/~alan-griffiths/mir/fix-1276704/+merge/205357
3. Add an unexplained change to debian/rules
4. debian/changelog additions.

I think we need to do this more cleanly so we know what's actually going in to the merge. Otherwise there's no accurate historical log of what has changed and why.

I suggest starting dropping #2 and proposing it separately, directly to lp:mir with the trunk-0.15 branch as prereq. Unless it lands in development-branch beforehand, which would be cleaner. I also would like to know where #3 (debian/rules change) has come from, and some documentation of that change.

It would reflect badly on mir-team if we review changes to development-branch carefully, but don't do the same for lp:mir and let in undocumented changes.

review: Needs Fixing
Daniel van Vugt (vanvugt) wrote :

BTW, if Ubuntu is desperate for it then you can always merge fix-1276704 directly to lp:mir without review. But it could become a major conflict headache if we find it needs fixing before it hits development-branch. So best to let it land in development-branch first.

Daniel van Vugt (vanvugt) wrote :

Oooh, the mysterious debian/rules change #3 comes from the destination lp:mir. We'll have to revisit that...

I'll track issue #2 manually in LP and do an upstream Mir 0.1.5 release from r1377 to keep things as consistent as possible. So approved!

review: Approve
Daniel van Vugt (vanvugt) wrote :

I've made major enhancements to the changelog text. Needs review again.

lp:~mir-team/mir/trunk-0.1.5 updated on 2014-02-10
1180. By Daniel van Vugt on 2014-02-10

Fix indentation

lp:~mir-team/mir/trunk-0.1.5 updated on 2014-02-10
1181. By Daniel van Vugt on 2014-02-10

Remember to mention ABI bumps.

kevin gunn (kgunn72) wrote :

thanks for the clean up, looks good (i see now how you want to handle tag vs promotion)

review: Approve
Kevin DuBois (kdub) wrote :

Please make sure not to pick up rev1383 because it contains a nexus 10 bug: https://bugs.launchpad.net/mir/+bug/1278658. (this has a fix, up for review)

Kevin DuBois (kdub) wrote :

> Please make sure not to pick up rev1383 because it contains a nexus 10 bug:
> https://bugs.launchpad.net/mir/+bug/1278658. (this has a fix, up for review)

fixed in lp:mir/devel rev 1388

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-01-22 08:32:55 +0000
3+++ CMakeLists.txt 2014-02-10 09:00:06 +0000
4@@ -28,7 +28,7 @@
5
6 set(MIR_VERSION_MAJOR 0)
7 set(MIR_VERSION_MINOR 1)
8-set(MIR_VERSION_PATCH 4)
9+set(MIR_VERSION_PATCH 5)
10
11 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
12
13
14=== modified file 'debian/changelog'
15--- debian/changelog 2014-02-04 14:49:07 +0000
16+++ debian/changelog 2014-02-10 09:00:06 +0000
17@@ -1,3 +1,52 @@
18+mir (0.1.5-0ubuntu1) UNRELEASED; urgency=medium
19+
20+ * Cherry-picked from future release 0.1.6:
21+ - frontend, shell: provide the client process ID in the shell::Session
22+ interface (LP: #1276704)
23+ * New upstream release 0.1.5 (https://launchpad.net/mir/+milestone/0.1.5)
24+ - mirclient ABI bumped to 7
25+ - mirserver ABI bumped to 15
26+ - Refactoring to support client-controled RPC.
27+ - Add an translucent server example (use sparingly, this will kill
28+ performance!)
29+ - Add workaround for Qualcomm Snapdragon 8960 driver bug.
30+ - android-input: Improve debug output
31+ - Screen rotation support half done (rotation of the screen works but input
32+ rotation not implemented yet).
33+ - Add groundwork for overlay support to take better advantage of mobile
34+ hardware features and optimize composition in future.
35+ - Add support for HWC 1.2 (Android 4.4)
36+ - Add groundwork for screencasting (screen recording).
37+ - Optimized surface resizing, significantly reducing event flooding for
38+ some input configurations like touch.
39+ - Bugs fixed:
40+ . Surfaces no longer visible at all on Nexus 10 (LP: #1271853)
41+ . mir nested server failure: what(): error binding buffer to texture
42+ (LP: #1272041)
43+ . Unity does not process events from evdev device created before unity is
44+ restarted (autopilot tests) (LP: #1238417)
45+ . mir_unit_tests can't run on touch images any more (missing
46+ libumockdev.so.0) (LP: #1271434)
47+ . chmod 777 /tmp/mir_socket is no longer sufficient for non-root clients
48+ to connect to a root server (LP: #1272143)
49+ . Nexus7(2013) flo framerate maxes out at 30fps (LP: #1274189)
50+ . libmirserver user is unable to #include
51+ <mir/frontend/template_protobuf_message_processor.h> (LP: #1276162)
52+ . libmirclient user cannot "#include <mir/client/private.h>"
53+ (LP: #1276565)
54+ . AndroidInternalClient.internal_client_creation_and_use hangs on Nexus
55+ 10 (LP: #1270685)
56+ . Tests that use the InProcessServer bind the default socket file
57+ (LP: #1271604)
58+ . BasicConnector threads exit immediately (LP: #1271655)
59+ . Integration tests TestClientIPCRender.test_accelerated_render fails on
60+ Galaxy Nexus and Nexus4 (LP: #1272597)
61+ . Android backend unit-tests FTBS on amd64 (LP: #1276621)
62+ . Erroneous use of last_consumed in SwitchingBundle::compositor_acquire
63+ (LP: #1270964)
64+
65+ -- Kevin Gunn <kevin.gunn@canonical.com> Thu, 06 Feb 2014 10:54:17 -0600
66+
67 mir (0.1.4+14.04.20140204-0ubuntu1) trusty; urgency=medium
68
69 [ Daniel van Vugt ]
70
71=== modified file 'debian/control'
72--- debian/control 2014-01-23 08:21:21 +0000
73+++ debian/control 2014-02-10 09:00:06 +0000
74@@ -70,7 +70,7 @@
75 .
76 Contains the protocol's definition files.
77
78-Package: libmirserver14
79+Package: libmirserver15
80 Section: libs
81 Architecture: i386 amd64 armhf arm64
82 Multi-Arch: same
83@@ -116,7 +116,7 @@
84 Architecture: i386 amd64 armhf arm64
85 Multi-Arch: same
86 Pre-Depends: ${misc:Pre-Depends}
87-Depends: libmirserver14 (= ${binary:Version}),
88+Depends: libmirserver15 (= ${binary:Version}),
89 libmirprotobuf-dev (= ${binary:Version}),
90 mircommon-dev (= ${binary:Version}),
91 libglm-dev,
92@@ -128,7 +128,7 @@
93 .
94 Contains header files required to build Mir servers.
95
96-Package: libmirclient6
97+Package: libmirclient7
98 Section: libs
99 Architecture: i386 amd64 armhf arm64
100 Multi-Arch: same
101@@ -146,7 +146,7 @@
102 Architecture: i386 amd64 armhf arm64
103 Multi-Arch: same
104 Pre-Depends: ${misc:Pre-Depends}
105-Depends: libmirclient6 (= ${binary:Version}),
106+Depends: libmirclient7 (= ${binary:Version}),
107 libmirprotobuf-dev (= ${binary:Version}),
108 mircommon-dev (= ${binary:Version}),
109 ${misc:Depends},
110
111=== renamed file 'debian/libmirclient6.install' => 'debian/libmirclient7.install'
112--- debian/libmirclient6.install 2014-01-17 06:22:01 +0000
113+++ debian/libmirclient7.install 2014-02-10 09:00:06 +0000
114@@ -1,1 +1,1 @@
115-usr/lib/*/libmirclient.so.6
116+usr/lib/*/libmirclient.so.7
117
118=== renamed file 'debian/libmirserver14.install' => 'debian/libmirserver15.install'
119--- debian/libmirserver14.install 2014-01-17 06:22:01 +0000
120+++ debian/libmirserver15.install 2014-02-10 09:00:06 +0000
121@@ -1,1 +1,1 @@
122-usr/lib/*/libmirserver.so.14
123+usr/lib/*/libmirserver.so.15
124
125=== modified file 'debian/mir-utils.install'
126--- debian/mir-utils.install 2014-01-10 05:48:41 +0000
127+++ debian/mir-utils.install 2014-02-10 09:00:06 +0000
128@@ -1,2 +1,3 @@
129 usr/bin/mirping
130 usr/bin/mirout
131+usr/bin/mirscreencast
132
133=== modified file 'examples/demo-inprocess-surface-client/inprocess_egl_client.cpp'
134--- examples/demo-inprocess-surface-client/inprocess_egl_client.cpp 2014-01-13 06:12:33 +0000
135+++ examples/demo-inprocess-surface-client/inprocess_egl_client.cpp 2014-02-10 09:00:06 +0000
136@@ -1,5 +1,5 @@
137 /*
138- * Copyright © 2013 Canonical Ltd.
139+ * Copyright © 2013-2014 Canonical Ltd.
140 *
141 * This program is free software: you can redistribute it and/or modify
142 * it under the terms of the GNU General Public License version 3 as
143@@ -41,6 +41,8 @@
144
145 #include <xkbcommon/xkbcommon-keysyms.h>
146
147+#include <unistd.h>
148+
149 #include <functional>
150
151 #include <assert.h>
152@@ -93,7 +95,7 @@
153 .of_size(surface_size)
154 .of_buffer_usage(mg::BufferUsage::hardware)
155 .of_pixel_format(mir_pixel_format_argb_8888);
156- auto session = shell->open_session("Inprocess client", std::make_shared<NullEventSink>());
157+ auto session = shell->open_session(getpid(), "Inprocess client", std::make_shared<NullEventSink>());
158 // TODO: Why do we get an ID? ~racarr
159 auto surface = session->get_surface(shell->create_surface_for(session, params));
160
161
162=== modified file 'examples/render_surfaces.cpp'
163--- examples/render_surfaces.cpp 2014-01-29 12:51:30 +0000
164+++ examples/render_surfaces.cpp 2014-02-10 09:00:06 +0000
165@@ -419,8 +419,9 @@
166 */
167 {
168 mg::Buffer* buffer{nullptr};
169- s->swap_buffers(buffer);
170- s->swap_buffers(buffer);
171+ auto const complete = [&](mg::Buffer* new_buf){ buffer = new_buf; };
172+ s->swap_buffers(buffer, complete);
173+ s->swap_buffers(buffer, complete);
174 }
175
176 /*
177
178=== modified file 'include/platform/mir/graphics/display.h'
179--- include/platform/mir/graphics/display.h 2013-08-28 03:41:48 +0000
180+++ include/platform/mir/graphics/display.h 2014-02-10 09:00:06 +0000
181@@ -50,9 +50,9 @@
182 virtual void for_each_display_buffer(std::function<void(DisplayBuffer&)> const& f) = 0;
183
184 /**
185- * Gets the current output configuration.
186+ * Gets a copy of the current output configuration.
187 */
188- virtual std::shared_ptr<DisplayConfiguration> configuration() = 0;
189+ virtual std::unique_ptr<DisplayConfiguration> configuration() const = 0;
190
191 /**
192 * Sets a new output configuration.
193
194=== modified file 'include/server/mir/compositor/buffer_stream.h'
195--- include/server/mir/compositor/buffer_stream.h 2014-01-13 06:12:33 +0000
196+++ include/server/mir/compositor/buffer_stream.h 2014-02-10 09:00:06 +0000
197@@ -41,7 +41,7 @@
198 public:
199 virtual ~BufferStream() = default;
200
201- virtual void swap_client_buffers(graphics::Buffer*& buffer) = 0;
202+ virtual void swap_client_buffers(graphics::Buffer* old_buffer, std::function<void(graphics::Buffer* new_buffer)> complete) = 0;
203 virtual std::shared_ptr<graphics::Buffer>
204 lock_compositor_buffer(unsigned long frameno) = 0;
205 virtual std::shared_ptr<graphics::Buffer> lock_snapshot_buffer() = 0;
206
207=== modified file 'include/server/mir/default_server_configuration.h'
208--- include/server/mir/default_server_configuration.h 2014-01-27 17:47:06 +0000
209+++ include/server/mir/default_server_configuration.h 2014-02-10 09:00:06 +0000
210@@ -50,6 +50,7 @@
211 class SessionAuthorizer;
212 class EventSink;
213 class DisplayChanger;
214+class Screencast;
215 }
216
217 namespace shell
218@@ -171,6 +172,7 @@
219 virtual std::shared_ptr<frontend::Shell> the_frontend_shell();
220 virtual std::shared_ptr<frontend::EventSink> the_global_event_sink();
221 virtual std::shared_ptr<frontend::DisplayChanger> the_frontend_display_changer();
222+ virtual std::shared_ptr<frontend::Screencast> the_screencast();
223 /** @name frontend configuration - internal dependencies
224 * internal dependencies of frontend
225 * @{ */
226@@ -266,6 +268,7 @@
227 CachedPtr<frontend::SessionAuthorizer> session_authorizer;
228 CachedPtr<frontend::EventSink> global_event_sink;
229 CachedPtr<frontend::SessionCreator> session_creator;
230+ CachedPtr<frontend::Screencast> screencast;
231 CachedPtr<compositor::RendererFactory> renderer_factory;
232 CachedPtr<compositor::BufferStreamFactory> buffer_stream_factory;
233 CachedPtr<scene::SurfaceStack> surface_stack;
234
235=== modified file 'include/server/mir/frontend/message_processor.h'
236--- include/server/mir/frontend/message_processor.h 2014-01-22 15:54:11 +0000
237+++ include/server/mir/frontend/message_processor.h 2014-02-10 09:00:06 +0000
238@@ -19,6 +19,8 @@
239 #ifndef MIR_FRONTEND_MESSAGE_PROCESSOR_H_
240 #define MIR_FRONTEND_MESSAGE_PROCESSOR_H_
241
242+#include <google/protobuf/service.h>
243+
244 namespace mir
245 {
246 namespace protobuf
247@@ -32,11 +34,23 @@
248 {
249 namespace detail
250 {
251+class Invocation
252+{
253+public:
254+ Invocation(mir::protobuf::wire::Invocation const& invocation) :
255+ invocation(invocation) {}
256+
257+ const ::std::string& method_name() const;
258+ const ::std::string& parameters() const;
259+ ::google::protobuf::uint32 id() const;
260+private:
261+ mir::protobuf::wire::Invocation const& invocation;
262+};
263
264 class MessageProcessor
265 {
266 public:
267- virtual bool dispatch(mir::protobuf::wire::Invocation const& invocation) = 0;
268+ virtual bool dispatch(Invocation const& invocation) = 0;
269
270 protected:
271 MessageProcessor() = default;
272
273=== added file 'include/server/mir/frontend/screencast.h'
274--- include/server/mir/frontend/screencast.h 1970-01-01 00:00:00 +0000
275+++ include/server/mir/frontend/screencast.h 2014-02-10 09:00:06 +0000
276@@ -0,0 +1,55 @@
277+/*
278+ * Copyright © 2014 Canonical Ltd.
279+ *
280+ * This program is free software: you can redistribute it and/or modify it
281+ * under the terms of the GNU General Public License version 3,
282+ * as published by the Free Software Foundation.
283+ *
284+ * This program is distributed in the hope that it will be useful,
285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
287+ * GNU General Public License for more details.
288+ *
289+ * You should have received a copy of the GNU General Public License
290+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
291+ *
292+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
293+ */
294+
295+#ifndef MIR_FRONTEND_SCREENCAST_H_
296+#define MIR_FRONTEND_SCREENCAST_H_
297+
298+#include "mir/int_wrapper.h"
299+#include "mir/graphics/display_configuration.h"
300+
301+#include <memory>
302+
303+namespace mir
304+{
305+namespace graphics { class Buffer; }
306+namespace frontend
307+{
308+namespace detail { struct ScreencastSessionIdTag; }
309+
310+typedef IntWrapper<detail::ScreencastSessionIdTag,uint32_t> ScreencastSessionId;
311+
312+class Screencast
313+{
314+public:
315+ virtual ~Screencast() = default;
316+
317+ virtual ScreencastSessionId create_session(
318+ graphics::DisplayConfigurationOutputId output_id) = 0;
319+ virtual void destroy_session(ScreencastSessionId id) = 0;
320+ virtual std::shared_ptr<graphics::Buffer> capture(ScreencastSessionId id) = 0;
321+
322+protected:
323+ Screencast() = default;
324+ Screencast(Screencast const&) = delete;
325+ Screencast& operator=(Screencast const&) = delete;
326+};
327+
328+}
329+}
330+
331+#endif /* MIR_FRONTEND_SCREENCAST_H_ */
332
333=== modified file 'include/server/mir/frontend/shell.h'
334--- include/server/mir/frontend/shell.h 2014-01-13 06:12:33 +0000
335+++ include/server/mir/frontend/shell.h 2014-02-10 09:00:06 +0000
336@@ -1,5 +1,5 @@
337 /*
338- * Copyright © 2012 Canonical Ltd.
339+ * Copyright © 2012-2014 Canonical Ltd.
340 *
341 * This program is free software: you can redistribute it and/or modify it
342 * under the terms of the GNU General Public License version 3,
343@@ -20,6 +20,9 @@
344 #define MIR_FRONTEND_SHELL_H_
345
346 #include "mir/frontend/surface_id.h"
347+
348+#include <sys/types.h>
349+
350 #include <memory>
351
352 namespace mir
353@@ -39,7 +42,10 @@
354 virtual ~Shell() = default;
355
356 virtual std::shared_ptr<Session> open_session(
357- std::string const& name, std::shared_ptr<EventSink> const& sink) = 0;
358+ pid_t client_pid,
359+ std::string const& name,
360+ std::shared_ptr<EventSink> const& sink) = 0;
361+
362 virtual void close_session(std::shared_ptr<Session> const& session) = 0;
363
364 virtual SurfaceId create_surface_for(std::shared_ptr<Session> const& session,
365
366=== modified file 'include/server/mir/frontend/surface.h'
367--- include/server/mir/frontend/surface.h 2014-01-13 06:12:33 +0000
368+++ include/server/mir/frontend/surface.h 2014-02-10 09:00:06 +0000
369@@ -56,13 +56,20 @@
370 virtual geometry::Size size() const = 0;
371 virtual MirPixelFormat pixel_format() const = 0;
372
373- virtual void swap_buffers(graphics::Buffer*&) = 0;
374+ virtual void swap_buffers(graphics::Buffer* old_buffer, std::function<void(graphics::Buffer* new_buffer)> complete) = 0;
375
376 virtual bool supports_input() const = 0;
377 virtual int client_input_fd() const = 0;
378
379 virtual int configure(MirSurfaceAttrib attrib, int value) = 0;
380
381+ /**
382+ * swap_buffers_blocking() is a convenience wrapper around swap_buffers()
383+ * it forces the current thread to block until complete() is called.
384+ * Use with care!
385+ */
386+ void swap_buffers_blocking(graphics::Buffer*& buffer);
387+
388 protected:
389 Surface() = default;
390 Surface(Surface const&) = delete;
391
392=== modified file 'include/server/mir/frontend/template_protobuf_message_processor.h'
393--- include/server/mir/frontend/template_protobuf_message_processor.h 2014-01-21 12:49:00 +0000
394+++ include/server/mir/frontend/template_protobuf_message_processor.h 2014-02-10 09:00:06 +0000
395@@ -22,8 +22,6 @@
396
397 #include "mir/frontend/message_processor.h"
398
399-#include "mir_protobuf_wire.pb.h"
400-
401 #include <google/protobuf/service.h>
402
403 #include <boost/exception/diagnostic_information.hpp>
404@@ -54,7 +52,7 @@
405 const ParameterMessage* request,
406 ResultMessage* response,
407 ::google::protobuf::Closure* done),
408- mir::protobuf::wire::Invocation const& invocation)
409+ Invocation const& invocation)
410 {
411 ParameterMessage parameter_message;
412 parameter_message.ParseFromString(invocation.parameters());
413
414=== modified file 'include/server/mir/shell/session.h'
415--- include/server/mir/shell/session.h 2014-01-13 06:12:33 +0000
416+++ include/server/mir/shell/session.h 2014-02-10 09:00:06 +0000
417@@ -1,5 +1,5 @@
418 /*
419- * Copyright © 2012 Canonical Ltd.
420+ * Copyright © 2012-2014 Canonical Ltd.
421 *
422 * This program is free software: you can redistribute it and/or modify it
423 * under the terms of the GNU General Public License version 3,
424@@ -7,11 +7,11 @@
425 *
426 * This program is distributed in the hope that it will be useful,
427 * but WITHOUT ANY WARRANTY; without even the implied warranty of
428- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
429+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
430 * GNU General Public License for more details.
431 *
432 * You should have received a copy of the GNU General Public License
433- * along with this program. If not, see <http://www.gnu.org/licenses/>.
434+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
435 *
436 * Authored By: Robert Carr <racarr@canonical.com>
437 */
438@@ -22,9 +22,10 @@
439 #include "mir/frontend/session.h"
440 #include "mir/shell/snapshot.h"
441
442+#include <sys/types.h>
443+
444 namespace mir
445 {
446-
447 namespace shell
448 {
449 class Surface;
450@@ -34,12 +35,12 @@
451 public:
452 virtual std::string name() const = 0;
453 virtual void force_requests_to_complete() = 0;
454+ virtual pid_t process_id() const = 0;
455
456 virtual void take_snapshot(SnapshotCallback const& snapshot_taken) = 0;
457 virtual std::shared_ptr<Surface> default_surface() const = 0;
458 virtual void set_lifecycle_state(MirLifecycleState state) = 0;
459 };
460-
461 }
462 }
463
464
465=== modified file 'include/shared/mir/int_wrapper.h'
466--- include/shared/mir/int_wrapper.h 2013-08-28 03:41:48 +0000
467+++ include/shared/mir/int_wrapper.h 2014-02-10 09:00:06 +0000
468@@ -23,12 +23,10 @@
469
470 namespace mir
471 {
472-template<typename Tag>
473+template<typename Tag, typename ValueType=int>
474 class IntWrapper
475 {
476 public:
477- typedef int ValueType;
478-
479 IntWrapper() : value(0) {}
480
481 explicit IntWrapper(ValueType value) : value(value) {}
482@@ -38,39 +36,39 @@
483 ValueType value;
484 };
485
486-template<typename Tag>
487-std::ostream& operator<<(std::ostream& out, IntWrapper<Tag> const& value)
488+template<typename Tag, typename ValueType>
489+std::ostream& operator<<(std::ostream& out, IntWrapper<Tag,ValueType> const& value)
490 {
491 out << value.as_value();
492 return out;
493 }
494
495-template<typename Tag>
496-inline bool operator == (IntWrapper<Tag> const& lhs, IntWrapper<Tag> const& rhs)
497+template<typename Tag, typename ValueType>
498+inline bool operator == (IntWrapper<Tag,ValueType> const& lhs, IntWrapper<Tag,ValueType> const& rhs)
499 {
500 return lhs.as_value() == rhs.as_value();
501 }
502
503-template<typename Tag>
504-inline bool operator != (IntWrapper<Tag> const& lhs, IntWrapper<Tag> const& rhs)
505+template<typename Tag, typename ValueType>
506+inline bool operator != (IntWrapper<Tag,ValueType> const& lhs, IntWrapper<Tag,ValueType> const& rhs)
507 {
508 return lhs.as_value() != rhs.as_value();
509 }
510
511-template<typename Tag>
512-inline bool operator <= (IntWrapper<Tag> const& lhs, IntWrapper<Tag> const& rhs)
513+template<typename Tag, typename ValueType>
514+inline bool operator <= (IntWrapper<Tag,ValueType> const& lhs, IntWrapper<Tag,ValueType> const& rhs)
515 {
516 return lhs.as_value() <= rhs.as_value();
517 }
518
519-template<typename Tag>
520-inline bool operator >= (IntWrapper<Tag> const& lhs, IntWrapper<Tag> const& rhs)
521+template<typename Tag, typename ValueType>
522+inline bool operator >= (IntWrapper<Tag,ValueType> const& lhs, IntWrapper<Tag,ValueType> const& rhs)
523 {
524 return lhs.as_value() >= rhs.as_value();
525 }
526
527-template<typename Tag>
528-inline bool operator < (IntWrapper<Tag> const& lhs, IntWrapper<Tag> const& rhs)
529+template<typename Tag, typename ValueType>
530+inline bool operator < (IntWrapper<Tag,ValueType> const& lhs, IntWrapper<Tag,ValueType> const& rhs)
531 {
532 return lhs.as_value() < rhs.as_value();
533 }
534@@ -79,11 +77,11 @@
535 #include <functional>
536 namespace std
537 {
538-template<typename Tag>
539-struct hash< ::mir::IntWrapper<Tag> >
540+template<typename Tag, typename ValueType>
541+struct hash< ::mir::IntWrapper<Tag,ValueType> >
542 {
543 std::hash<int> self;
544- std::size_t operator()(::mir::IntWrapper<Tag> const& id) const
545+ std::size_t operator()(::mir::IntWrapper<Tag,ValueType> const& id) const
546 {
547 return self(id.as_value());
548 }
549
550=== modified file 'include/test/mir_test_doubles/mock_buffer_bundle.h'
551--- include/test/mir_test_doubles/mock_buffer_bundle.h 2014-01-13 06:12:33 +0000
552+++ include/test/mir_test_doubles/mock_buffer_bundle.h 2014-02-10 09:00:06 +0000
553@@ -37,7 +37,7 @@
554 ~MockBufferBundle() noexcept
555 {}
556
557- MOCK_METHOD0(client_acquire, graphics::Buffer*());
558+ MOCK_METHOD1(client_acquire, void(std::function<void(graphics::Buffer*)>));
559 MOCK_METHOD1(client_release, void(graphics::Buffer*));
560 MOCK_METHOD1(compositor_acquire, std::shared_ptr<graphics::Buffer>(unsigned long));
561 MOCK_METHOD1(compositor_release, void(std::shared_ptr<graphics::Buffer> const&));
562
563=== modified file 'include/test/mir_test_doubles/mock_buffer_stream.h'
564--- include/test/mir_test_doubles/mock_buffer_stream.h 2014-01-13 06:12:33 +0000
565+++ include/test/mir_test_doubles/mock_buffer_stream.h 2014-02-10 09:00:06 +0000
566@@ -31,7 +31,7 @@
567 {
568 struct MockBufferStream : public compositor::BufferStream
569 {
570- MOCK_METHOD1(swap_client_buffers, void(graphics::Buffer*&));
571+ MOCK_METHOD2(swap_client_buffers, void(graphics::Buffer*, std::function<void(graphics::Buffer*)> completee));
572 MOCK_METHOD1(lock_compositor_buffer,
573 std::shared_ptr<graphics::Buffer>(unsigned long));
574 MOCK_METHOD0(lock_snapshot_buffer, std::shared_ptr<graphics::Buffer>());
575
576=== modified file 'include/test/mir_test_doubles/mock_display.h'
577--- include/test/mir_test_doubles/mock_display.h 2013-08-28 03:41:48 +0000
578+++ include/test/mir_test_doubles/mock_display.h 2014-02-10 09:00:06 +0000
579@@ -36,7 +36,7 @@
580 {
581 public:
582 MOCK_METHOD1(for_each_display_buffer, void (std::function<void(graphics::DisplayBuffer&)> const&));
583- MOCK_METHOD0(configuration, std::shared_ptr<graphics::DisplayConfiguration>());
584+ MOCK_CONST_METHOD0(configuration, std::unique_ptr<graphics::DisplayConfiguration>());
585 MOCK_METHOD1(configure, void(graphics::DisplayConfiguration const&));
586 MOCK_METHOD2(register_configuration_change_handler,
587 void(graphics::EventHandlerRegister&, graphics::DisplayConfigurationChangeHandler const&));
588
589=== modified file 'include/test/mir_test_doubles/mock_fb_hal_device.h'
590--- include/test/mir_test_doubles/mock_fb_hal_device.h 2014-01-13 06:12:33 +0000
591+++ include/test/mir_test_doubles/mock_fb_hal_device.h 2014-02-10 09:00:06 +0000
592@@ -37,7 +37,7 @@
593 MockFBHalDevice(unsigned int const width, unsigned int const height,
594 int const pf, int const numfbs)
595 : framebuffer_device_t({
596- empty_module,
597+ hw_device_t(),
598 0,
599 width,
600 height,
601@@ -86,8 +86,6 @@
602 MOCK_METHOD2(enableScreen_interface, int(struct framebuffer_device_t*, int));
603 MOCK_METHOD2(post_interface, int(struct framebuffer_device_t*, buffer_handle_t));
604 MOCK_METHOD2(setSwapInterval_interface, int(struct framebuffer_device_t*, int));
605-
606- hw_device_t empty_module;
607 };
608
609 }
610
611=== modified file 'include/test/mir_test_doubles/mock_frontend_surface.h'
612--- include/test/mir_test_doubles/mock_frontend_surface.h 2014-01-13 06:12:33 +0000
613+++ include/test/mir_test_doubles/mock_frontend_surface.h 2014-02-10 09:00:06 +0000
614@@ -39,7 +39,7 @@
615
616 MOCK_METHOD0(destroy, void());
617 MOCK_METHOD0(force_requests_to_complete, void());
618- MOCK_METHOD1(swap_buffers, void(graphics::Buffer*&));
619+ MOCK_METHOD2(swap_buffers, void(graphics::Buffer*, std::function<void(graphics::Buffer*)> complete));
620
621 MOCK_CONST_METHOD0(size, geometry::Size());
622 MOCK_CONST_METHOD0(pixel_format, MirPixelFormat());
623
624=== modified file 'include/test/mir_test_doubles/mock_hwc_composer_device_1.h'
625--- include/test/mir_test_doubles/mock_hwc_composer_device_1.h 2014-01-23 17:26:51 +0000
626+++ include/test/mir_test_doubles/mock_hwc_composer_device_1.h 2014-02-10 09:00:06 +0000
627@@ -76,6 +76,11 @@
628 fb_fence = fence;
629 }
630
631+ void hwc_set_retire_fence(int fence)
632+ {
633+ retire_fence = fence;
634+ }
635+
636 int save_last_prepare_arguments(struct hwc_composer_device_1 *, size_t size, hwc_display_contents_1_t** displays)
637 {
638 if ((size == 0) || (!displays))
639@@ -122,12 +127,14 @@
640 set_layerlist.back().visibleRegionScreen = {0, nullptr};
641 }
642
643+ save_args(&display0_set_content, displays);
644+
645 if (displays[0]->numHwLayers >= 2)
646 {
647 displays[0]->hwLayers[1].releaseFenceFd = fb_fence;
648+ displays[0]->retireFenceFd = retire_fence;
649 }
650
651- save_args(&display0_set_content, displays);
652 default:
653 break;
654 }
655@@ -186,6 +193,7 @@
656 std::vector<hwc_layer_1> prepare_layerlist;
657 hwc_display_contents_1_t display0_prepare_content;
658 int fb_fence;
659+ int retire_fence;
660 };
661
662 }
663
664=== added file 'include/test/mir_test_doubles/mock_screencast.h'
665--- include/test/mir_test_doubles/mock_screencast.h 1970-01-01 00:00:00 +0000
666+++ include/test/mir_test_doubles/mock_screencast.h 2014-02-10 09:00:06 +0000
667@@ -0,0 +1,50 @@
668+/*
669+ * Copyright © 2014 Canonical Ltd.
670+ *
671+ * This program is free software: you can redistribute it and/or modify it
672+ * under the terms of the GNU General Public License version 3,
673+ * as published by the Free Software Foundation.
674+ *
675+ * This program is distributed in the hope that it will be useful,
676+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
677+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
678+ * GNU General Public License for more details.
679+ *
680+ * You should have received a copy of the GNU General Public License
681+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
682+ *
683+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
684+ */
685+
686+#ifndef MIR_TEST_DOUBLES_MOCK_SCREENCAST_H_
687+#define MIR_TEST_DOUBLES_MOCK_SCREENCAST_H_
688+
689+#include "mir/frontend/screencast.h"
690+
691+#include <gmock/gmock.h>
692+
693+namespace mir
694+{
695+namespace test
696+{
697+namespace doubles
698+{
699+
700+class MockScreencast : public frontend::Screencast
701+{
702+public:
703+ MOCK_METHOD1(create_session,
704+ frontend::ScreencastSessionId(
705+ graphics::DisplayConfigurationOutputId));
706+ MOCK_METHOD1(destroy_session, void(frontend::ScreencastSessionId));
707+ MOCK_METHOD1(capture,
708+ std::shared_ptr<graphics::Buffer>(
709+ frontend::ScreencastSessionId));
710+};
711+
712+}
713+}
714+}
715+
716+#endif /* MIR_TEST_DOUBLES_NULL_SCREENCAST_H_ */
717+
718
719=== modified file 'include/test/mir_test_doubles/mock_shell.h'
720--- include/test/mir_test_doubles/mock_shell.h 2013-08-28 03:41:48 +0000
721+++ include/test/mir_test_doubles/mock_shell.h 2014-02-10 09:00:06 +0000
722@@ -1,5 +1,5 @@
723 /*
724- * Copyright © 2013 Canonical Ltd.
725+ * Copyright © 2013-2014 Canonical Ltd.
726 *
727 * This program is free software: you can redistribute it and/or modify
728 * it under the terms of the GNU General Public License version 3 as
729@@ -34,8 +34,11 @@
730
731 struct MockShell : public frontend::Shell
732 {
733- MOCK_METHOD2(open_session, std::shared_ptr<frontend::Session>(
734- std::string const&, std::shared_ptr<frontend::EventSink> const&));
735+ MOCK_METHOD3(open_session, std::shared_ptr<frontend::Session>(
736+ pid_t client_pid,
737+ std::string const&,
738+ std::shared_ptr<frontend::EventSink> const&));
739+
740 MOCK_METHOD1(close_session, void(std::shared_ptr<frontend::Session> const&));
741
742 MOCK_METHOD2(create_surface_for, frontend::SurfaceId(std::shared_ptr<frontend::Session> const&, shell::SurfaceCreationParameters const&));
743
744=== modified file 'include/test/mir_test_doubles/mock_shell_session.h'
745--- include/test/mir_test_doubles/mock_shell_session.h 2014-01-13 06:12:33 +0000
746+++ include/test/mir_test_doubles/mock_shell_session.h 2014-02-10 09:00:06 +0000
747@@ -1,5 +1,5 @@
748 /*
749- * Copyright © 2013 Canonical Ltd.
750+ * Copyright © 2013-2014 Canonical Ltd.
751 *
752 * This program is free software: you can redistribute it and/or modify it
753 * under the terms of the GNU General Public License version 3,
754@@ -42,6 +42,7 @@
755 MOCK_CONST_METHOD0(default_surface, std::shared_ptr<shell::Surface>());
756
757 MOCK_CONST_METHOD0(name, std::string());
758+ MOCK_CONST_METHOD0(process_id, pid_t());
759 MOCK_METHOD0(force_requests_to_complete, void());
760
761 MOCK_METHOD0(hide, void());
762
763=== modified file 'include/test/mir_test_doubles/null_display.h'
764--- include/test/mir_test_doubles/null_display.h 2013-08-28 03:41:48 +0000
765+++ include/test/mir_test_doubles/null_display.h 2014-02-10 09:00:06 +0000
766@@ -39,9 +39,11 @@
767 /* yield() is needed to ensure reasonable runtime under valgrind for some tests */
768 std::this_thread::yield();
769 }
770- std::shared_ptr<graphics::DisplayConfiguration> configuration()
771+ std::unique_ptr<graphics::DisplayConfiguration> configuration() const override
772 {
773- return std::make_shared<NullDisplayConfiguration>();
774+ return std::unique_ptr<graphics::DisplayConfiguration>(
775+ new NullDisplayConfiguration
776+ );
777 }
778 void configure(graphics::DisplayConfiguration const&) {}
779 void register_configuration_change_handler(
780
781=== added file 'include/test/mir_test_doubles/null_screencast.h'
782--- include/test/mir_test_doubles/null_screencast.h 1970-01-01 00:00:00 +0000
783+++ include/test/mir_test_doubles/null_screencast.h 2014-02-10 09:00:06 +0000
784@@ -0,0 +1,52 @@
785+/*
786+ * Copyright © 2014 Canonical Ltd.
787+ *
788+ * This program is free software: you can redistribute it and/or modify it
789+ * under the terms of the GNU General Public License version 3,
790+ * as published by the Free Software Foundation.
791+ *
792+ * This program is distributed in the hope that it will be useful,
793+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
794+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
795+ * GNU General Public License for more details.
796+ *
797+ * You should have received a copy of the GNU General Public License
798+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
799+ *
800+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
801+ */
802+
803+#ifndef MIR_TEST_DOUBLES_NULL_SCREENCAST_H_
804+#define MIR_TEST_DOUBLES_NULL_SCREENCAST_H_
805+
806+#include "mir/frontend/screencast.h"
807+
808+namespace mir
809+{
810+namespace test
811+{
812+namespace doubles
813+{
814+
815+class NullScreencast : public frontend::Screencast
816+{
817+public:
818+ frontend::ScreencastSessionId create_session(
819+ graphics::DisplayConfigurationOutputId)
820+ {
821+ return frontend::ScreencastSessionId{1};
822+ }
823+
824+ void destroy_session(frontend::ScreencastSessionId) {}
825+
826+ std::shared_ptr<graphics::Buffer> capture(frontend::ScreencastSessionId)
827+ {
828+ return nullptr;
829+ }
830+};
831+
832+}
833+}
834+}
835+
836+#endif /* MIR_TEST_DOUBLES_NULL_SCREENCAST_H_ */
837
838=== modified file 'include/test/mir_test_doubles/stub_buffer_stream.h'
839--- include/test/mir_test_doubles/stub_buffer_stream.h 2014-01-13 06:12:33 +0000
840+++ include/test/mir_test_doubles/stub_buffer_stream.h 2014-02-10 09:00:06 +0000
841@@ -36,9 +36,9 @@
842 {
843 stub_compositor_buffer = std::make_shared<StubBuffer>();
844 }
845- void swap_client_buffers(graphics::Buffer*& buffer) override
846+ void swap_client_buffers(graphics::Buffer*, std::function<void(graphics::Buffer* new_buffer)> complete) override
847 {
848- buffer = &stub_client_buffer;
849+ complete(&stub_client_buffer);
850 }
851 std::shared_ptr<graphics::Buffer> lock_compositor_buffer(unsigned long) override
852 {
853
854=== modified file 'include/test/mir_test_doubles/stub_display_configuration.h'
855--- include/test/mir_test_doubles/stub_display_configuration.h 2014-01-28 09:06:46 +0000
856+++ include/test/mir_test_doubles/stub_display_configuration.h 2014-02-10 09:00:06 +0000
857@@ -40,6 +40,13 @@
858 {
859 }
860
861+ StubDisplayConfig(StubDisplayConfig const& other)
862+ : graphics::DisplayConfiguration(),
863+ cards(other.cards),
864+ outputs(other.outputs)
865+ {
866+ }
867+
868 StubDisplayConfig(unsigned int num_displays)
869 : StubDisplayConfig(num_displays,
870 {
871
872=== modified file 'include/test/mir_test_doubles/stub_ipc_factory.h'
873--- include/test/mir_test_doubles/stub_ipc_factory.h 2014-01-21 06:27:40 +0000
874+++ include/test/mir_test_doubles/stub_ipc_factory.h 2014-02-10 09:00:06 +0000
875@@ -1,5 +1,5 @@
876 /*
877- * Copyright © 2012 Canonical Ltd.
878+ * Copyright © 2012-2014 Canonical Ltd.
879 *
880 * This program is free software: you can redistribute it and/or modify it
881 * under the terms of the GNU General Public License version 3,
882@@ -41,7 +41,7 @@
883 }
884
885 std::shared_ptr<protobuf::DisplayServer> make_ipc_server(
886- std::shared_ptr<frontend::EventSink> const&, bool) override
887+ pid_t, std::shared_ptr<frontend::EventSink> const&, bool) override
888 {
889 return server;
890 }
891
892=== modified file 'include/test/mir_test_doubles/stub_shell.h'
893--- include/test/mir_test_doubles/stub_shell.h 2013-08-28 03:41:48 +0000
894+++ include/test/mir_test_doubles/stub_shell.h 2014-02-10 09:00:06 +0000
895@@ -34,7 +34,7 @@
896 StubShell() : stub_session(std::make_shared<StubSession>())
897 {
898 }
899- std::shared_ptr<frontend::Session> open_session(std::string const& /* name */, std::shared_ptr<frontend::EventSink> const& /* sink */) override
900+ std::shared_ptr<frontend::Session> open_session(pid_t, std::string const& /* name */, std::shared_ptr<frontend::EventSink> const& /* sink */) override
901 {
902 return stub_session;
903 }
904
905=== modified file 'include/test/mir_test_doubles/stub_shell_session.h'
906--- include/test/mir_test_doubles/stub_shell_session.h 2014-01-13 06:12:33 +0000
907+++ include/test/mir_test_doubles/stub_shell_session.h 2014-02-10 09:00:06 +0000
908@@ -1,5 +1,5 @@
909 /*
910- * Copyright © 2013 Canonical Ltd.
911+ * Copyright © 2013-2014 Canonical Ltd.
912 *
913 * This program is free software: you can redistribute it and/or modify it
914 * under the terms of the GNU General Public License version 3,
915@@ -45,6 +45,11 @@
916 {
917 return std::string();
918 }
919+ pid_t process_id() const override
920+ {
921+ return -1;
922+ }
923+
924 void force_requests_to_complete() override
925 {
926 }
927
928=== modified file 'src/client/CMakeLists.txt'
929--- src/client/CMakeLists.txt 2014-01-28 09:06:46 +0000
930+++ src/client/CMakeLists.txt 2014-02-10 09:00:06 +0000
931@@ -72,7 +72,7 @@
932 ${CLIENT_SOURCES}
933 )
934
935-set(MIRCLIENT_ABI 6)
936+set(MIRCLIENT_ABI 7)
937
938 set_target_properties(
939 mirclient
940@@ -117,7 +117,7 @@
941 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
942
943 install(
944- DIRECTORY ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit
945+ DIRECTORY ${CMAKE_SOURCE_DIR}/include/client/mir_toolkit ${CMAKE_SOURCE_DIR}/include/client/mir
946 DESTINATION "include/mirclient"
947 )
948
949
950=== modified file 'src/client/mir_screencast.cpp'
951--- src/client/mir_screencast.cpp 2014-01-24 18:11:19 +0000
952+++ src/client/mir_screencast.cpp 2014-02-10 09:00:06 +0000
953@@ -98,6 +98,8 @@
954 egl_native_window_factory{egl_native_window_factory},
955 buffer_depository{factory, mir::frontend::client_buffer_cache_size}
956 {
957+ protobuf_screencast.set_error("Not initialized");
958+
959 mir::protobuf::ScreencastParameters parameters;
960 parameters.set_output_id(output_id);
961 parameters.set_width(output_size.width.as_uint32_t());
962@@ -117,6 +119,11 @@
963 return &create_screencast_wait_handle;
964 }
965
966+bool MirScreencast::valid()
967+{
968+ return !protobuf_screencast.has_error();
969+}
970+
971 MirSurfaceParameters MirScreencast::get_parameters() const
972 {
973 return MirSurfaceParameters{
974@@ -188,7 +195,7 @@
975 try
976 {
977 buffer_depository.deposit_package(buffer_package,
978- protobuf_buffer.buffer_id(),
979+ buffer.buffer_id(),
980 output_size, output_format);
981 }
982 catch (const std::runtime_error& err)
983@@ -200,8 +207,11 @@
984 void MirScreencast::screencast_created(
985 mir_screencast_callback callback, void* context)
986 {
987- egl_native_window_ = egl_native_window_factory->create_egl_native_window(this);
988- process_buffer(protobuf_screencast.buffer());
989+ if (!protobuf_screencast.has_error())
990+ {
991+ egl_native_window_ = egl_native_window_factory->create_egl_native_window(this);
992+ process_buffer(protobuf_screencast.buffer());
993+ }
994
995 callback(this, context);
996 create_screencast_wait_handle.result_received();
997
998=== modified file 'src/client/mir_screencast.h'
999--- src/client/mir_screencast.h 2014-01-24 18:11:19 +0000
1000+++ src/client/mir_screencast.h 2014-02-10 09:00:06 +0000
1001@@ -49,6 +49,7 @@
1002 mir_screencast_callback callback, void* context);
1003
1004 MirWaitHandle* creation_wait_handle();
1005+ bool valid();
1006
1007 MirWaitHandle* release(
1008 mir_screencast_callback callback, void* context);
1009
1010=== modified file 'src/client/mir_screencast_api.cpp'
1011--- src/client/mir_screencast_api.cpp 2014-01-29 09:16:50 +0000
1012+++ src/client/mir_screencast_api.cpp 2014-02-10 09:00:06 +0000
1013@@ -64,14 +64,21 @@
1014
1015 auto const client_platform = connection->get_client_platform();
1016
1017- screencast = new MirScreencast{
1018- find_display_output(*config, parameters->output_id),
1019- connection->display_server(),
1020- client_platform,
1021- client_platform->create_buffer_factory(),
1022- null_callback, nullptr};
1023-
1024- screencast->creation_wait_handle()->wait_for_all();
1025+ std::unique_ptr<MirScreencast> screencast_uptr{
1026+ new MirScreencast{
1027+ find_display_output(*config, parameters->output_id),
1028+ connection->display_server(),
1029+ client_platform,
1030+ client_platform->create_buffer_factory(),
1031+ null_callback, nullptr}};
1032+
1033+ screencast_uptr->creation_wait_handle()->wait_for_all();
1034+
1035+ if (screencast_uptr->valid())
1036+ {
1037+ screencast = screencast_uptr.get();
1038+ screencast_uptr.release();
1039+ }
1040 }
1041 catch (std::exception const&)
1042 {
1043
1044=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
1045--- src/client/rpc/mir_socket_rpc_channel.cpp 2014-01-13 06:12:33 +0000
1046+++ src/client/rpc/mir_socket_rpc_channel.cpp 2014-02-10 09:00:06 +0000
1047@@ -143,6 +143,7 @@
1048 if (!disconnected.load())
1049 {
1050 auto surface = dynamic_cast<mir::protobuf::Surface*>(response);
1051+ mir::protobuf::Screencast* screencast{nullptr};
1052 if (surface)
1053 {
1054 surface->clear_fd();
1055@@ -157,12 +158,18 @@
1056 rpc_report->file_descriptors_received(*response, fds);
1057 }
1058 }
1059+ else
1060+ {
1061+ screencast = dynamic_cast<mir::protobuf::Screencast*>(response);
1062+ }
1063
1064 auto buffer = dynamic_cast<mir::protobuf::Buffer*>(response);
1065 if (!buffer)
1066 {
1067 if (surface && surface->has_buffer())
1068 buffer = surface->mutable_buffer();
1069+ else if (screencast && screencast->has_buffer())
1070+ buffer = screencast->mutable_buffer();
1071 }
1072
1073 if (buffer)
1074
1075=== modified file 'src/platform/graphics/android/android_alloc_adaptor.cpp'
1076--- src/platform/graphics/android/android_alloc_adaptor.cpp 2014-01-13 06:12:33 +0000
1077+++ src/platform/graphics/android/android_alloc_adaptor.cpp 2014-02-10 09:00:06 +0000
1078@@ -69,7 +69,7 @@
1079 }
1080
1081 AndroidBufferHandleDeleter del1(alloc_dev);
1082- std::shared_ptr<native_handle_t> handle(buf_handle, del1);
1083+ std::shared_ptr<native_handle_t const> handle(buf_handle, del1);
1084
1085 auto ops = std::make_shared<mga::RealSyncFileOps>();
1086 auto fence = std::make_shared<mga::SyncFence>(ops, -1);
1087
1088=== modified file 'src/platform/graphics/android/android_display.cpp'
1089--- src/platform/graphics/android/android_display.cpp 2014-01-21 06:27:40 +0000
1090+++ src/platform/graphics/android/android_display.cpp 2014-02-10 09:00:06 +0000
1091@@ -52,9 +52,11 @@
1092 f(*display_buffer);
1093 }
1094
1095-std::shared_ptr<mg::DisplayConfiguration> mga::AndroidDisplay::configuration()
1096+std::unique_ptr<mg::DisplayConfiguration> mga::AndroidDisplay::configuration() const
1097 {
1098- return std::make_shared<mga::AndroidDisplayConfiguration>(current_configuration);
1099+ return std::unique_ptr<mg::DisplayConfiguration>(
1100+ new mga::AndroidDisplayConfiguration(current_configuration)
1101+ );
1102 }
1103
1104 void mga::AndroidDisplay::configure(mg::DisplayConfiguration const& configuration)
1105
1106=== modified file 'src/platform/graphics/android/android_display.h'
1107--- src/platform/graphics/android/android_display.h 2014-01-13 06:12:33 +0000
1108+++ src/platform/graphics/android/android_display.h 2014-02-10 09:00:06 +0000
1109@@ -48,8 +48,8 @@
1110
1111 void for_each_display_buffer(std::function<void(graphics::DisplayBuffer&)> const& f);
1112
1113- std::shared_ptr<DisplayConfiguration> configuration();
1114- void configure(DisplayConfiguration const&);
1115+ std::unique_ptr<DisplayConfiguration> configuration() const override;
1116+ void configure(DisplayConfiguration const&) override;
1117
1118 void register_configuration_change_handler(
1119 EventHandlerRegister& handlers,
1120
1121=== modified file 'src/platform/graphics/android/android_platform.cpp'
1122--- src/platform/graphics/android/android_platform.cpp 2014-01-13 06:12:33 +0000
1123+++ src/platform/graphics/android/android_platform.cpp 2014-02-10 09:00:06 +0000
1124@@ -107,13 +107,11 @@
1125
1126 extern "C" std::shared_ptr<mg::Platform> mg::create_platform(std::shared_ptr<mo::Option> const& /*options*/, std::shared_ptr<DisplayReport> const& display_report)
1127 {
1128- //todo: could parse an option here
1129- auto should_use_fb_fallback = false;
1130 auto buffer_initializer = std::make_shared<mg::NullBufferInitializer>();
1131 auto display_resource_factory = std::make_shared<mga::ResourceFactory>();
1132 auto fb_allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>(buffer_initializer);
1133 auto display_builder = std::make_shared<mga::OutputBuilder>(
1134- fb_allocator, display_resource_factory, display_report, should_use_fb_fallback);
1135+ fb_allocator, display_resource_factory, display_report);
1136 return std::make_shared<mga::AndroidPlatform>(display_builder, display_report);
1137 }
1138
1139
1140=== modified file 'src/platform/graphics/android/display_buffer.h'
1141--- src/platform/graphics/android/display_buffer.h 2014-01-23 17:26:51 +0000
1142+++ src/platform/graphics/android/display_buffer.h 2014-02-10 09:00:06 +0000
1143@@ -61,7 +61,6 @@
1144 std::shared_ptr<DisplayDevice> const display_device;
1145 std::shared_ptr<ANativeWindow> const native_window;
1146 GLContext gl_context;
1147- bool prepared;
1148 MirOrientation rotation;
1149 };
1150
1151
1152=== modified file 'src/platform/graphics/android/hwc_device.cpp'
1153--- src/platform/graphics/android/hwc_device.cpp 2014-01-23 18:01:19 +0000
1154+++ src/platform/graphics/android/hwc_device.cpp 2014-02-10 09:00:06 +0000
1155@@ -35,10 +35,11 @@
1156 namespace geom = mir::geometry;
1157
1158 mga::HwcDevice::HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
1159- std::shared_ptr<HWCVsyncCoordinator> const& coordinator)
1160+ std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
1161+ std::shared_ptr<SyncFileOps> const& sync_ops)
1162 : HWCCommonDevice(hwc_device, coordinator),
1163 layer_list({mga::ForceGLLayer{}, mga::FramebufferLayer{}}),
1164- sync_ops(std::make_shared<mga::RealSyncFileOps>())
1165+ sync_ops(sync_ops)
1166 {
1167 }
1168
1169@@ -79,12 +80,8 @@
1170 BOOST_THROW_EXCEPTION(std::runtime_error("error during hwc set()"));
1171 }
1172
1173- if (last_display_fence)
1174- last_display_fence->wait();
1175+ mga::SyncFence retire_fence(sync_ops, displays[HWC_DISPLAY_PRIMARY]->retireFenceFd);
1176
1177 int framebuffer_fence = layer_list.framebuffer_fence();
1178 native_buffer->update_fence(framebuffer_fence);
1179-
1180- last_display_fence = std::make_shared<mga::SyncFence>(
1181- sync_ops, displays[HWC_DISPLAY_PRIMARY]->retireFenceFd);
1182 }
1183
1184=== modified file 'src/platform/graphics/android/hwc_device.h'
1185--- src/platform/graphics/android/hwc_device.h 2014-01-23 18:01:19 +0000
1186+++ src/platform/graphics/android/hwc_device.h 2014-02-10 09:00:06 +0000
1187@@ -34,13 +34,13 @@
1188 {
1189 class HWCVsyncCoordinator;
1190 class SyncFileOps;
1191-class SyncFence;
1192
1193 class HwcDevice : public HWCCommonDevice
1194 {
1195 public:
1196 HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
1197- std::shared_ptr<HWCVsyncCoordinator> const& coordinator);
1198+ std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
1199+ std::shared_ptr<SyncFileOps> const& sync_ops);
1200
1201 void prepare_gl();
1202 void prepare_gl_and_overlays(std::list<std::shared_ptr<Renderable>> const& list);
1203@@ -50,10 +50,7 @@
1204 private:
1205 LayerList layer_list;
1206
1207- std::shared_ptr<SyncFence> last_display_fence;
1208 std::shared_ptr<SyncFileOps> const sync_ops;
1209- unsigned int primary_display_config;
1210- MirPixelFormat fb_format;
1211 static size_t const num_displays{3}; //primary, external, virtual
1212 };
1213
1214
1215=== modified file 'src/platform/graphics/android/hwc_layers.cpp'
1216--- src/platform/graphics/android/hwc_layers.cpp 2014-01-24 21:50:21 +0000
1217+++ src/platform/graphics/android/hwc_layers.cpp 2014-02-10 09:00:06 +0000
1218@@ -30,14 +30,18 @@
1219
1220 mga::HWCLayer& mga::HWCLayer::operator=(HWCLayer const& layer)
1221 {
1222- memcpy(this, &layer, sizeof(HWCLayer));
1223+ memcpy(static_cast<void*>(this),
1224+ static_cast<void const*>(&layer),
1225+ sizeof(HWCLayer));
1226 this->visibleRegionScreen = {1, &this->visible_rect};
1227 return *this;
1228 }
1229
1230 mga::HWCLayer::HWCLayer(HWCLayer const& layer)
1231 {
1232- memcpy(this, &layer, sizeof(HWCLayer));
1233+ memcpy(static_cast<void*>(this),
1234+ static_cast<void const*>(&layer),
1235+ sizeof(HWCLayer));
1236 this->visibleRegionScreen = {1, &this->visible_rect};
1237 }
1238
1239
1240=== modified file 'src/platform/graphics/android/internal_client_window.cpp'
1241--- src/platform/graphics/android/internal_client_window.cpp 2014-01-13 06:12:33 +0000
1242+++ src/platform/graphics/android/internal_client_window.cpp 2014-02-10 09:00:06 +0000
1243@@ -25,6 +25,7 @@
1244
1245 #include <boost/throw_exception.hpp>
1246 #include <stdexcept>
1247+#include <sstream>
1248
1249 namespace mg=mir::graphics;
1250 namespace mga=mg::android;
1251@@ -93,7 +94,11 @@
1252 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
1253 return 1;
1254 default:
1255- BOOST_THROW_EXCEPTION(std::runtime_error("driver requests info we dont provide. key: " + key));
1256+ {
1257+ std::stringstream sstream;
1258+ sstream << "driver requests info we dont provide. key: " << key;
1259+ BOOST_THROW_EXCEPTION(std::runtime_error(sstream.str()));
1260+ }
1261 }
1262 }
1263
1264
1265=== modified file 'src/platform/graphics/android/output_builder.cpp'
1266--- src/platform/graphics/android/output_builder.cpp 2014-01-21 18:09:35 +0000
1267+++ src/platform/graphics/android/output_builder.cpp 2014-02-10 09:00:06 +0000
1268@@ -33,22 +33,18 @@
1269 mga::OutputBuilder::OutputBuilder(
1270 std::shared_ptr<mga::GraphicBufferAllocator> const& buffer_allocator,
1271 std::shared_ptr<mga::DisplayResourceFactory> const& res_factory,
1272- std::shared_ptr<mg::DisplayReport> const& display_report,
1273- bool should_use_fb_fallback)
1274+ std::shared_ptr<mg::DisplayReport> const& display_report)
1275 : buffer_allocator(buffer_allocator),
1276 res_factory(res_factory),
1277 display_report(display_report),
1278- force_backup_display(should_use_fb_fallback)
1279+ force_backup_display(false)
1280 {
1281- if (!force_backup_display)
1282- {
1283- try
1284- {
1285- hwc_native = res_factory->create_hwc_native_device();
1286- } catch (...)
1287- {
1288- force_backup_display = true;
1289- }
1290+ try
1291+ {
1292+ hwc_native = res_factory->create_hwc_native_device();
1293+ } catch (...)
1294+ {
1295+ force_backup_display = true;
1296 }
1297
1298 if (force_backup_display || hwc_native->common.version == HWC_DEVICE_API_VERSION_1_0)
1299
1300=== modified file 'src/platform/graphics/android/output_builder.h'
1301--- src/platform/graphics/android/output_builder.h 2014-01-13 06:12:33 +0000
1302+++ src/platform/graphics/android/output_builder.h 2014-02-10 09:00:06 +0000
1303@@ -40,8 +40,7 @@
1304 OutputBuilder(
1305 std::shared_ptr<GraphicBufferAllocator> const& buffer_allocator,
1306 std::shared_ptr<DisplayResourceFactory> const& res_factory,
1307- std::shared_ptr<DisplayReport> const& display_report,
1308- bool should_use_fb_fallback);
1309+ std::shared_ptr<DisplayReport> const& display_report);
1310
1311 MirPixelFormat display_format();
1312 std::shared_ptr<DisplayDevice> create_display_device();
1313
1314=== modified file 'src/platform/graphics/android/resource_factory.cpp'
1315--- src/platform/graphics/android/resource_factory.cpp 2014-01-21 18:09:35 +0000
1316+++ src/platform/graphics/android/resource_factory.cpp 2014-02-10 09:00:06 +0000
1317@@ -18,6 +18,7 @@
1318 */
1319
1320 #include "mir/graphics/android/mir_native_window.h"
1321+#include "mir/graphics/android/sync_fence.h"
1322 #include "buffer.h"
1323 #include "resource_factory.h"
1324 #include "fb_device.h"
1325@@ -91,7 +92,8 @@
1326 std::shared_ptr<hwc_composer_device_1> const& hwc_native_device) const
1327 {
1328 auto syncer = std::make_shared<mga::HWCVsync>();
1329- return std::make_shared<mga::HwcDevice>(hwc_native_device, syncer);
1330+ auto file_ops = std::make_shared<mga::RealSyncFileOps>();
1331+ return std::make_shared<mga::HwcDevice>(hwc_native_device, syncer, file_ops);
1332 }
1333
1334 std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(
1335
1336=== modified file 'src/platform/graphics/android/server_render_window.cpp'
1337--- src/platform/graphics/android/server_render_window.cpp 2014-01-13 06:12:33 +0000
1338+++ src/platform/graphics/android/server_render_window.cpp 2014-02-10 09:00:06 +0000
1339@@ -28,6 +28,7 @@
1340 #include <system/window.h>
1341 #include <boost/throw_exception.hpp>
1342 #include <stdexcept>
1343+#include <sstream>
1344
1345 namespace mg=mir::graphics;
1346 namespace mga=mir::graphics::android;
1347@@ -81,7 +82,11 @@
1348 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
1349 return 1;
1350 default:
1351- BOOST_THROW_EXCEPTION(std::runtime_error("driver requests info we dont provide. key: " + key));
1352+ {
1353+ std::stringstream sstream;
1354+ sstream << "driver requests info we dont provide. key: " << key;
1355+ BOOST_THROW_EXCEPTION(std::runtime_error(sstream.str()));
1356+ }
1357 }
1358 }
1359
1360
1361=== modified file 'src/platform/graphics/mesa/display.cpp'
1362--- src/platform/graphics/mesa/display.cpp 2014-01-22 08:32:55 +0000
1363+++ src/platform/graphics/mesa/display.cpp 2014-02-10 09:00:06 +0000
1364@@ -115,13 +115,15 @@
1365 f(*db_ptr);
1366 }
1367
1368-std::shared_ptr<mg::DisplayConfiguration> mgm::Display::configuration()
1369+std::unique_ptr<mg::DisplayConfiguration> mgm::Display::configuration() const
1370 {
1371 std::lock_guard<std::mutex> lg{configuration_mutex};
1372
1373 /* Give back a copy of the latest configuration information */
1374 current_display_configuration.update();
1375- return std::make_shared<mgm::RealKMSDisplayConfiguration>(current_display_configuration);
1376+ return std::unique_ptr<mg::DisplayConfiguration>(
1377+ new mgm::RealKMSDisplayConfiguration(current_display_configuration)
1378+ );
1379 }
1380
1381 void mgm::Display::configure(mg::DisplayConfiguration const& conf)
1382
1383=== modified file 'src/platform/graphics/mesa/display.h'
1384--- src/platform/graphics/mesa/display.h 2014-01-22 08:32:55 +0000
1385+++ src/platform/graphics/mesa/display.h 2014-02-10 09:00:06 +0000
1386@@ -62,8 +62,8 @@
1387 void for_each_display_buffer(
1388 std::function<void(graphics::DisplayBuffer&)> const& f);
1389
1390- std::shared_ptr<DisplayConfiguration> configuration();
1391- void configure(DisplayConfiguration const& conf);
1392+ std::unique_ptr<DisplayConfiguration> configuration() const override;
1393+ void configure(DisplayConfiguration const& conf) override;
1394
1395 void register_configuration_change_handler(
1396 EventHandlerRegister& handlers,
1397@@ -83,14 +83,14 @@
1398 private:
1399 void clear_connected_unused_outputs();
1400
1401- std::mutex configuration_mutex;
1402+ mutable std::mutex configuration_mutex;
1403 std::shared_ptr<Platform> const platform;
1404 std::shared_ptr<DisplayReport> const listener;
1405 mir::udev::Monitor monitor;
1406 helpers::EGLHelper shared_egl;
1407 std::vector<std::unique_ptr<DisplayBuffer>> display_buffers;
1408 RealKMSOutputContainer output_container;
1409- RealKMSDisplayConfiguration current_display_configuration;
1410+ mutable RealKMSDisplayConfiguration current_display_configuration;
1411 std::shared_ptr<Cursor> cursor;
1412 };
1413
1414
1415=== modified file 'src/server/CMakeLists.txt'
1416--- src/server/CMakeLists.txt 2014-01-22 08:32:55 +0000
1417+++ src/server/CMakeLists.txt 2014-02-10 09:00:06 +0000
1418@@ -94,7 +94,7 @@
1419 )
1420 endif()
1421
1422-set(MIRSERVER_ABI 14)
1423+set(MIRSERVER_ABI 15)
1424
1425 set_target_properties(
1426 mirserver
1427
1428=== modified file 'src/server/compositor/buffer_bundle.h'
1429--- src/server/compositor/buffer_bundle.h 2014-01-13 06:12:33 +0000
1430+++ src/server/compositor/buffer_bundle.h 2014-02-10 09:00:06 +0000
1431@@ -34,7 +34,7 @@
1432 {
1433 public:
1434 virtual ~BufferBundle() noexcept {}
1435- virtual graphics::Buffer* client_acquire() = 0;
1436+ virtual void client_acquire(std::function<void(graphics::Buffer* buffer)> complete) = 0;
1437 virtual void client_release(graphics::Buffer*) = 0;
1438 virtual std::shared_ptr<graphics::Buffer>
1439 compositor_acquire(unsigned long frameno) = 0;
1440
1441=== modified file 'src/server/compositor/buffer_stream_surfaces.cpp'
1442--- src/server/compositor/buffer_stream_surfaces.cpp 2014-01-13 06:12:33 +0000
1443+++ src/server/compositor/buffer_stream_surfaces.cpp 2014-02-10 09:00:06 +0000
1444@@ -49,13 +49,14 @@
1445 return std::make_shared<mc::TemporarySnapshotBuffer>(buffer_bundle);
1446 }
1447
1448-void mc::BufferStreamSurfaces::swap_client_buffers(mg::Buffer*& buffer)
1449+void mc::BufferStreamSurfaces::swap_client_buffers(graphics::Buffer* old_buffer, std::function<void(graphics::Buffer* new_buffer)> complete)
1450 {
1451- if (buffer)
1452+ if (old_buffer)
1453 {
1454- buffer_bundle->client_release(buffer);
1455+ buffer_bundle->client_release(old_buffer);
1456 }
1457- buffer = buffer_bundle->client_acquire();
1458+
1459+ buffer_bundle->client_acquire(complete);
1460 }
1461
1462 MirPixelFormat mc::BufferStreamSurfaces::get_stream_pixel_format()
1463
1464=== modified file 'src/server/compositor/buffer_stream_surfaces.h'
1465--- src/server/compositor/buffer_stream_surfaces.h 2014-01-13 06:12:33 +0000
1466+++ src/server/compositor/buffer_stream_surfaces.h 2014-02-10 09:00:06 +0000
1467@@ -39,7 +39,7 @@
1468 BufferStreamSurfaces(std::shared_ptr<BufferBundle> const& swapper);
1469 ~BufferStreamSurfaces();
1470
1471- void swap_client_buffers(graphics::Buffer*& buffer) override;
1472+ void swap_client_buffers(graphics::Buffer* old_buffer, std::function<void(graphics::Buffer* new_buffer)> complete) override;
1473
1474 std::shared_ptr<graphics::Buffer>
1475 lock_compositor_buffer(unsigned long frameno) override;
1476
1477=== modified file 'src/server/compositor/default_configuration.cpp'
1478--- src/server/compositor/default_configuration.cpp 2014-01-13 06:12:33 +0000
1479+++ src/server/compositor/default_configuration.cpp 2014-02-10 09:00:06 +0000
1480@@ -17,13 +17,17 @@
1481 */
1482
1483 #include "mir/default_server_configuration.h"
1484+#include "mir/frontend/screencast.h"
1485 #include "buffer_stream_factory.h"
1486 #include "default_display_buffer_compositor_factory.h"
1487 #include "multi_threaded_compositor.h"
1488 #include "gl_renderer_factory.h"
1489
1490+#include <boost/throw_exception.hpp>
1491+
1492 namespace mc = mir::compositor;
1493 namespace ms = mir::scene;
1494+namespace mf = mir::frontend;
1495
1496 std::shared_ptr<ms::BufferStreamFactory>
1497 mir::DefaultServerConfiguration::the_buffer_stream_factory()
1498@@ -67,3 +71,31 @@
1499 return std::make_shared<mc::GLRendererFactory>();
1500 });
1501 }
1502+
1503+std::shared_ptr<mf::Screencast> mir::DefaultServerConfiguration::the_screencast()
1504+{
1505+ struct NotImplementedScreencast : mf::Screencast
1506+ {
1507+ mf::ScreencastSessionId create_session(
1508+ graphics::DisplayConfigurationOutputId)
1509+ {
1510+ BOOST_THROW_EXCEPTION(std::runtime_error("Screencast not implemented"));
1511+ }
1512+
1513+ void destroy_session(mf::ScreencastSessionId)
1514+ {
1515+ BOOST_THROW_EXCEPTION(std::runtime_error("Screencast not implemented"));
1516+ }
1517+
1518+ std::shared_ptr<graphics::Buffer> capture(mf::ScreencastSessionId)
1519+ {
1520+ BOOST_THROW_EXCEPTION(std::runtime_error("Screencast not implemented"));
1521+ }
1522+ };
1523+
1524+ return screencast(
1525+ [this]()
1526+ {
1527+ return std::make_shared<NotImplementedScreencast>();
1528+ });
1529+}
1530
1531=== modified file 'src/server/compositor/switching_bundle.cpp'
1532--- src/server/compositor/switching_bundle.cpp 2014-01-23 18:42:20 +0000
1533+++ src/server/compositor/switching_bundle.cpp 2014-02-10 09:00:06 +0000
1534@@ -177,7 +177,7 @@
1535 return ring[slot].buf;
1536 }
1537
1538-mg::Buffer* mc::SwitchingBundle::client_acquire()
1539+void mc::SwitchingBundle::client_acquire(std::function<void(graphics::Buffer* buffer)> complete)
1540 {
1541 std::unique_lock<std::mutex> lock(guard);
1542
1543@@ -247,7 +247,7 @@
1544 ring[client].buf = ret;
1545 }
1546
1547- return ret.get();
1548+ complete(ret.get());
1549 }
1550
1551 void mc::SwitchingBundle::client_release(graphics::Buffer* released_buffer)
1552
1553=== modified file 'src/server/compositor/switching_bundle.h'
1554--- src/server/compositor/switching_bundle.h 2014-01-23 18:42:20 +0000
1555+++ src/server/compositor/switching_bundle.h 2014-02-10 09:00:06 +0000
1556@@ -49,7 +49,7 @@
1557
1558 graphics::BufferProperties properties() const;
1559
1560- graphics::Buffer* client_acquire();
1561+ void client_acquire(std::function<void(graphics::Buffer* buffer)> complete) override;
1562 void client_release(graphics::Buffer* buffer);
1563 std::shared_ptr<graphics::Buffer>
1564 compositor_acquire(unsigned long frameno) override;
1565
1566=== modified file 'src/server/display_server.cpp'
1567--- src/server/display_server.cpp 2013-10-16 07:34:22 +0000
1568+++ src/server/display_server.cpp 2014-02-10 09:00:06 +0000
1569@@ -27,6 +27,7 @@
1570 #include "mir/compositor/compositor.h"
1571 #include "mir/frontend/connector.h"
1572 #include "mir/graphics/display.h"
1573+#include "mir/graphics/display_configuration.h"
1574 #include "mir/input/input_manager.h"
1575
1576 #include <stdexcept>
1577@@ -134,7 +135,8 @@
1578
1579 if (configure_display_on_resume)
1580 {
1581- auto conf = display->configuration();
1582+ std::shared_ptr<graphics::DisplayConfiguration> conf =
1583+ display->configuration();
1584 display_changer->configure_for_hardware_change(
1585 conf, DisplayChanger::RetainSystemState);
1586 configure_display_on_resume = false;
1587@@ -162,7 +164,8 @@
1588 {
1589 if (!paused)
1590 {
1591- auto conf = display->configuration();
1592+ std::shared_ptr<graphics::DisplayConfiguration> conf =
1593+ display->configuration();
1594 display_changer->configure_for_hardware_change(
1595 conf, DisplayChanger::PauseResumeSystem);
1596 }
1597
1598=== modified file 'src/server/frontend/default_configuration.cpp'
1599--- src/server/frontend/default_configuration.cpp 2014-01-29 12:51:30 +0000
1600+++ src/server/frontend/default_configuration.cpp 2014-02-10 09:00:06 +0000
1601@@ -1,5 +1,5 @@
1602 /*
1603- * Copyright © 2012 Canonical Ltd.
1604+ * Copyright © 2012-2014 Canonical Ltd.
1605 *
1606 * This program is free software: you can redistribute it and/or modify it
1607 * under the terms of the GNU General Public License version 3,
1608@@ -42,13 +42,15 @@
1609 std::shared_ptr<mf::SessionMediatorReport> const& sm_report,
1610 std::shared_ptr<mg::Platform> const& graphics_platform,
1611 std::shared_ptr<mf::DisplayChanger> const& display_changer,
1612- std::shared_ptr<mg::GraphicBufferAllocator> const& buffer_allocator) :
1613+ std::shared_ptr<mg::GraphicBufferAllocator> const& buffer_allocator,
1614+ std::shared_ptr<mf::Screencast> const& screencast) :
1615 shell(shell),
1616 sm_report(sm_report),
1617 cache(std::make_shared<mf::ResourceCache>()),
1618 graphics_platform(graphics_platform),
1619 display_changer(display_changer),
1620- buffer_allocator(buffer_allocator)
1621+ buffer_allocator(buffer_allocator),
1622+ screencast(screencast)
1623 {
1624 }
1625
1626@@ -59,9 +61,12 @@
1627 std::shared_ptr<mg::Platform> const graphics_platform;
1628 std::shared_ptr<mf::DisplayChanger> const display_changer;
1629 std::shared_ptr<mg::GraphicBufferAllocator> const buffer_allocator;
1630+ std::shared_ptr<mf::Screencast> const screencast;
1631
1632 virtual std::shared_ptr<mir::protobuf::DisplayServer> make_ipc_server(
1633- std::shared_ptr<mf::EventSink> const& sink, bool authorized_to_resize_display)
1634+ pid_t client_pid,
1635+ std::shared_ptr<mf::EventSink> const& sink,
1636+ bool authorized_to_resize_display) override
1637 {
1638 std::shared_ptr<mf::DisplayChanger> changer;
1639 if(authorized_to_resize_display)
1640@@ -74,13 +79,15 @@
1641 }
1642
1643 return std::make_shared<mf::SessionMediator>(
1644+ client_pid,
1645 shell,
1646 graphics_platform,
1647 changer,
1648 buffer_allocator->supported_pixel_formats(),
1649 sm_report,
1650 sink,
1651- resource_cache());
1652+ resource_cache(),
1653+ screencast);
1654 }
1655
1656 virtual std::shared_ptr<mf::ResourceCache> resource_cache()
1657@@ -144,6 +151,8 @@
1658 shell,
1659 the_session_mediator_report(),
1660 the_graphics_platform(),
1661- the_frontend_display_changer(), allocator);
1662+ the_frontend_display_changer(),
1663+ allocator,
1664+ the_screencast());
1665 });
1666 }
1667
1668=== modified file 'src/server/frontend/protobuf_ipc_factory.h'
1669--- src/server/frontend/protobuf_ipc_factory.h 2014-01-21 06:27:40 +0000
1670+++ src/server/frontend/protobuf_ipc_factory.h 2014-02-10 09:00:06 +0000
1671@@ -1,5 +1,5 @@
1672 /*
1673- * Copyright © 2012 Canonical Ltd.
1674+ * Copyright © 2012-2014 Canonical Ltd.
1675 *
1676 * This program is free software: you can redistribute it and/or modify it
1677 * under the terms of the GNU General Public License version 3,
1678@@ -19,6 +19,8 @@
1679 #ifndef MIR_FRONTEND_PROTOBUF_IPC_FACTORY_H_
1680 #define MIR_FRONTEND_PROTOBUF_IPC_FACTORY_H_
1681
1682+#include <sys/types.h>
1683+
1684 #include <memory>
1685
1686 namespace mir
1687@@ -37,7 +39,10 @@
1688 {
1689 public:
1690 virtual std::shared_ptr<protobuf::DisplayServer> make_ipc_server(
1691- std::shared_ptr<EventSink> const& sink, bool authorized_to_resize_display) = 0;
1692+ pid_t client_pid,
1693+ std::shared_ptr<EventSink> const& sink,
1694+ bool authorized_to_resize_display) = 0;
1695+
1696 virtual std::shared_ptr<ResourceCache> resource_cache() = 0;
1697
1698 protected:
1699
1700=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
1701--- src/server/frontend/protobuf_message_processor.cpp 2014-01-28 09:06:46 +0000
1702+++ src/server/frontend/protobuf_message_processor.cpp 2014-02-10 09:00:06 +0000
1703@@ -21,6 +21,8 @@
1704 #include "mir/frontend/protobuf_message_sender.h"
1705 #include "mir/frontend/template_protobuf_message_processor.h"
1706
1707+#include "mir_protobuf_wire.pb.h"
1708+
1709 namespace mfd = mir::frontend::detail;
1710
1711 namespace
1712@@ -54,11 +56,70 @@
1713 template<> struct result_ptr_t<::mir::protobuf::Buffer> { typedef ::mir::protobuf::Buffer* type; };
1714 template<> struct result_ptr_t<::mir::protobuf::Connection> { typedef ::mir::protobuf::Connection* type; };
1715 template<> struct result_ptr_t<::mir::protobuf::Surface> { typedef ::mir::protobuf::Surface* type; };
1716-}
1717-}
1718-}
1719-
1720-bool mfd::ProtobufMessageProcessor::dispatch(mir::protobuf::wire::Invocation const& invocation)
1721+template<> struct result_ptr_t<::mir::protobuf::Screencast> { typedef ::mir::protobuf::Screencast* type; };
1722+
1723+template<>
1724+void invoke(
1725+ ProtobufMessageProcessor* self,
1726+ protobuf::DisplayServer* server,
1727+ void (protobuf::DisplayServer::*function)(
1728+ ::google::protobuf::RpcController* controller,
1729+ const protobuf::SurfaceId* request,
1730+ protobuf::Buffer* response,
1731+ ::google::protobuf::Closure* done),
1732+ Invocation const& invocation)
1733+{
1734+ protobuf::SurfaceId parameter_message;
1735+ parameter_message.ParseFromString(invocation.parameters());
1736+ auto const result_message = std::make_shared<protobuf::Buffer>();
1737+
1738+ auto const callback =
1739+ google::protobuf::NewCallback<
1740+ ProtobufMessageProcessor,
1741+ ::google::protobuf::uint32,
1742+ std::shared_ptr<protobuf::Buffer>>(
1743+ self,
1744+ &ProtobufMessageProcessor::send_response,
1745+ invocation.id(),
1746+ result_message);
1747+
1748+ try
1749+ {
1750+ (server->*function)(
1751+ 0,
1752+ &parameter_message,
1753+ result_message.get(),
1754+ callback);
1755+ }
1756+ catch (std::exception const& x)
1757+ {
1758+ delete callback;
1759+ result_message->set_error(boost::diagnostic_information(x));
1760+ self->send_response(invocation.id(), result_message);
1761+ }
1762+}
1763+}
1764+}
1765+}
1766+
1767+
1768+const std::string& mfd::Invocation::method_name() const
1769+{
1770+ return invocation.method_name();
1771+}
1772+
1773+const std::string& mfd::Invocation::parameters() const
1774+{
1775+ return invocation.parameters();
1776+}
1777+
1778+google::protobuf::uint32 mfd::Invocation::id() const
1779+{
1780+ return invocation.id();
1781+}
1782+
1783+
1784+bool mfd::ProtobufMessageProcessor::dispatch(Invocation const& invocation)
1785 {
1786 report->received_invocation(display_server.get(), invocation.id(), invocation.method_name());
1787
1788@@ -145,6 +206,11 @@
1789 sender->send_response(id, response, {fd});
1790 }
1791
1792+void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, std::shared_ptr<protobuf::Buffer> response)
1793+{
1794+ send_response(id, response.get());
1795+}
1796+
1797 void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::Connection* response)
1798 {
1799 const auto& fd = response->has_platform() ?
1800@@ -163,3 +229,13 @@
1801
1802 sender->send_response(id, response, {surface_fd, buffer_fd});
1803 }
1804+
1805+void mfd::ProtobufMessageProcessor::send_response(
1806+ ::google::protobuf::uint32 id, mir::protobuf::Screencast* response)
1807+{
1808+ auto const& buffer_fd = response->has_buffer() ?
1809+ extract_fds_from(response->mutable_buffer()) :
1810+ std::vector<int32_t>();
1811+
1812+ sender->send_response(id, response, {buffer_fd});
1813+}
1814
1815=== modified file 'src/server/frontend/protobuf_message_processor.h'
1816--- src/server/frontend/protobuf_message_processor.h 2014-01-22 15:54:11 +0000
1817+++ src/server/frontend/protobuf_message_processor.h 2014-02-10 09:00:06 +0000
1818@@ -52,9 +52,11 @@
1819 void send_response(::google::protobuf::uint32 id, protobuf::Buffer* response);
1820 void send_response(::google::protobuf::uint32 id, protobuf::Connection* response);
1821 void send_response(::google::protobuf::uint32 id, protobuf::Surface* response);
1822+ void send_response(::google::protobuf::uint32 id, std::shared_ptr<protobuf::Buffer> response);
1823+ void send_response(::google::protobuf::uint32 id, mir::protobuf::Screencast* response);
1824
1825 private:
1826- bool dispatch(mir::protobuf::wire::Invocation const& invocation);
1827+ bool dispatch(Invocation const& invocation);
1828
1829 std::shared_ptr<ProtobufMessageSender> const sender;
1830 std::shared_ptr<protobuf::DisplayServer> const display_server;
1831
1832=== modified file 'src/server/frontend/protobuf_session_creator.cpp'
1833--- src/server/frontend/protobuf_session_creator.cpp 2014-01-22 15:54:11 +0000
1834+++ src/server/frontend/protobuf_session_creator.cpp 2014-02-10 09:00:06 +0000
1835@@ -1,5 +1,5 @@
1836 /*
1837- * Copyright © 2013 Canonical Ltd.
1838+ * Copyright © 2013-2014 Canonical Ltd.
1839 *
1840 * This program is free software: you can redistribute it and/or modify it
1841 * under the terms of the GNU General Public License version 3,
1842@@ -69,7 +69,7 @@
1843 auto const event_sink = std::make_shared<detail::EventSender>(messenger);
1844 auto const msg_processor = create_processor(
1845 message_sender,
1846- ipc_factory->make_ipc_server(event_sink, authorized_to_resize_display),
1847+ ipc_factory->make_ipc_server(client_pid, event_sink, authorized_to_resize_display),
1848 report);
1849
1850 const auto& session = std::make_shared<mfd::SocketSession>(messenger, next_id(), connected_sessions, msg_processor);
1851
1852=== modified file 'src/server/frontend/session_mediator.cpp'
1853--- src/server/frontend/session_mediator.cpp 2014-01-13 06:12:33 +0000
1854+++ src/server/frontend/session_mediator.cpp 2014-02-10 09:00:06 +0000
1855@@ -1,5 +1,5 @@
1856 /*
1857- * Copyright © 2012 Canonical Ltd.
1858+ * Copyright © 2012-2014 Canonical Ltd.
1859 *
1860 * This program is free software: you can redistribute it and/or modify it
1861 * under the terms of the GNU General Public License version 3,
1862@@ -38,6 +38,7 @@
1863 #include "mir/graphics/platform_ipc_package.h"
1864 #include "mir/frontend/client_constants.h"
1865 #include "mir/frontend/event_sink.h"
1866+#include "mir/frontend/screencast.h"
1867
1868 #include "mir/geometry/rectangles.h"
1869 #include "client_buffer_tracker.h"
1870@@ -55,20 +56,24 @@
1871 namespace geom = mir::geometry;
1872
1873 mf::SessionMediator::SessionMediator(
1874+ pid_t client_pid,
1875 std::shared_ptr<frontend::Shell> const& shell,
1876 std::shared_ptr<graphics::Platform> const & graphics_platform,
1877 std::shared_ptr<mf::DisplayChanger> const& display_changer,
1878 std::vector<MirPixelFormat> const& surface_pixel_formats,
1879 std::shared_ptr<SessionMediatorReport> const& report,
1880 std::shared_ptr<EventSink> const& sender,
1881- std::shared_ptr<ResourceCache> const& resource_cache) :
1882+ std::shared_ptr<ResourceCache> const& resource_cache,
1883+ std::shared_ptr<Screencast> const& screencast) :
1884+ client_pid(client_pid),
1885 shell(shell),
1886 graphics_platform(graphics_platform),
1887 surface_pixel_formats(surface_pixel_formats),
1888 display_changer(display_changer),
1889 report(report),
1890 event_sink(sender),
1891- resource_cache(resource_cache)
1892+ resource_cache(resource_cache),
1893+ screencast(screencast)
1894 {
1895 }
1896
1897@@ -92,7 +97,7 @@
1898
1899 {
1900 std::unique_lock<std::mutex> lock(session_mutex);
1901- weak_session = shell->open_session(request->application_name(), event_sink);
1902+ weak_session = shell->open_session(client_pid, request->application_name(), event_sink);
1903 }
1904
1905 auto ipc_package = graphics_platform->get_ipc_package();
1906@@ -116,19 +121,25 @@
1907 done->Run();
1908 }
1909
1910-std::tuple<mg::Buffer*, bool>
1911-mf::SessionMediator::advance_buffer(SurfaceId surf_id, Surface& surface)
1912+void mf::SessionMediator::advance_buffer(
1913+ SurfaceId surf_id,
1914+ Surface& surface,
1915+ std::function<void(graphics::Buffer*, bool)> complete)
1916 {
1917 auto& tracker = client_buffer_tracker[surf_id];
1918 if (!tracker) tracker = std::make_shared<ClientBufferTracker>(client_buffer_cache_size);
1919
1920 auto& client_buffer = client_buffer_resource[surf_id];
1921- surface.swap_buffers(client_buffer);
1922- auto id = client_buffer->id();
1923- auto need_full_ipc = !tracker->client_has(id);
1924- tracker->add(id);
1925+ surface.swap_buffers(client_buffer,
1926+ [&tracker, &client_buffer, complete](mg::Buffer* new_buffer)
1927+ {
1928+ client_buffer = new_buffer;
1929+ auto id = client_buffer->id();
1930+ auto need_full_ipc = !tracker->client_has(id);
1931+ tracker->add(id);
1932
1933- return std::tie(client_buffer, need_full_ipc);
1934+ complete(client_buffer, need_full_ipc);
1935+ });
1936 }
1937
1938
1939@@ -138,49 +149,48 @@
1940 mir::protobuf::Surface* response,
1941 google::protobuf::Closure* done)
1942 {
1943- bool need_full_ipc;
1944- graphics::Buffer* client_buffer{nullptr};
1945- std::shared_ptr<Session> session;
1946-
1947- {
1948- std::unique_lock<std::mutex> lock(session_mutex);
1949-
1950- session = weak_session.lock();
1951-
1952- if (session.get() == nullptr)
1953- BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
1954-
1955- report->session_create_surface_called(session->name());
1956-
1957- auto const surf_id = session->create_surface(msh::SurfaceCreationParameters()
1958- .of_name(request->surface_name())
1959- .of_size(request->width(), request->height())
1960- .of_buffer_usage(static_cast<graphics::BufferUsage>(request->buffer_usage()))
1961- .of_pixel_format(static_cast<MirPixelFormat>(request->pixel_format()))
1962- .with_output_id(graphics::DisplayConfigurationOutputId(request->output_id())));
1963-
1964- auto surface = session->get_surface(surf_id);
1965- response->mutable_id()->set_value(surf_id.as_value());
1966- response->set_width(surface->size().width.as_uint32_t());
1967- response->set_height(surface->size().height.as_uint32_t());
1968- response->set_pixel_format((int)surface->pixel_format());
1969- response->set_buffer_usage(request->buffer_usage());
1970-
1971- if (surface->supports_input())
1972- response->add_fd(surface->client_input_fd());
1973-
1974- std::tie(client_buffer, need_full_ipc) = advance_buffer(surf_id, *surface);
1975- }
1976-
1977- auto buffer = response->mutable_buffer();
1978- pack_protobuf_buffer(*buffer, client_buffer, need_full_ipc);
1979-
1980- // TODO: NOTE: We use the ordering here to ensure the shell acts on the surface after the surface ID is sent over the wire.
1981- // This guarantees that notifications such as, gained focus, etc, can be correctly interpreted by the client.
1982- // To achieve this order we rely on done->Run() sending messages synchronously. As documented in mfd::SocketMessenger::send.
1983- // this will require additional synchronization if mfd::SocketMessenger::send changes.
1984- done->Run();
1985- shell->handle_surface_created(session);
1986+
1987+ auto const lock = std::make_shared<std::unique_lock<std::mutex>>(session_mutex);
1988+
1989+ auto const session = weak_session.lock();
1990+
1991+ if (session.get() == nullptr)
1992+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
1993+
1994+ report->session_create_surface_called(session->name());
1995+
1996+ auto const surf_id = session->create_surface(msh::SurfaceCreationParameters()
1997+ .of_name(request->surface_name())
1998+ .of_size(request->width(), request->height())
1999+ .of_buffer_usage(static_cast<graphics::BufferUsage>(request->buffer_usage()))
2000+ .of_pixel_format(static_cast<MirPixelFormat>(request->pixel_format()))
2001+ .with_output_id(graphics::DisplayConfigurationOutputId(request->output_id())));
2002+
2003+ auto surface = session->get_surface(surf_id);
2004+ response->mutable_id()->set_value(surf_id.as_value());
2005+ response->set_width(surface->size().width.as_uint32_t());
2006+ response->set_height(surface->size().height.as_uint32_t());
2007+ response->set_pixel_format((int)surface->pixel_format());
2008+ response->set_buffer_usage(request->buffer_usage());
2009+
2010+ if (surface->supports_input())
2011+ response->add_fd(surface->client_input_fd());
2012+
2013+ advance_buffer(surf_id, *surface,
2014+ [lock, this, response, done, session](graphics::Buffer* client_buffer, bool need_full_ipc)
2015+ {
2016+ lock->unlock();
2017+
2018+ auto buffer = response->mutable_buffer();
2019+ pack_protobuf_buffer(*buffer, client_buffer, need_full_ipc);
2020+
2021+ // TODO: NOTE: We use the ordering here to ensure the shell acts on the surface after the surface ID is sent over the wire.
2022+ // This guarantees that notifications such as, gained focus, etc, can be correctly interpreted by the client.
2023+ // To achieve this order we rely on done->Run() sending messages synchronously. As documented in mfd::SocketMessenger::send.
2024+ // this will require additional synchronization if mfd::SocketMessenger::send changes.
2025+ done->Run();
2026+ shell->handle_surface_created(session);
2027+ });
2028 }
2029
2030 void mf::SessionMediator::next_buffer(
2031@@ -189,34 +199,34 @@
2032 ::mir::protobuf::Buffer* response,
2033 ::google::protobuf::Closure* done)
2034 {
2035- bool need_full_ipc;
2036 SurfaceId const surf_id{request->value()};
2037- graphics::Buffer* client_buffer{nullptr};
2038-
2039- {
2040- std::unique_lock<std::mutex> lock(session_mutex);
2041-
2042- auto session = weak_session.lock();
2043-
2044- if (session.get() == nullptr)
2045- BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
2046-
2047- report->session_next_buffer_called(session->name());
2048-
2049- // We ensure the client has not powered down the outputs, so that
2050- // swap_buffer will not block indefinitely, leaving the client
2051- // in a position where it can not turn back on the
2052- // outputs.
2053- display_changer->ensure_display_powered(session);
2054-
2055- auto surface = session->get_surface(surf_id);
2056-
2057- std::tie(client_buffer, need_full_ipc) = advance_buffer(surf_id, *surface);
2058- }
2059-
2060- pack_protobuf_buffer(*response, client_buffer, need_full_ipc);
2061-
2062- done->Run();
2063+
2064+ auto const lock = std::make_shared<std::unique_lock<std::mutex>>(session_mutex);
2065+
2066+ auto const session = weak_session.lock();
2067+
2068+ if (session.get() == nullptr)
2069+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session"));
2070+
2071+ report->session_next_buffer_called(session->name());
2072+
2073+ // We ensure the client has not powered down the outputs, so that
2074+ // swap_buffer will not block indefinitely, leaving the client
2075+ // in a position where it can not turn back on the
2076+ // outputs.
2077+ display_changer->ensure_display_powered(session);
2078+
2079+ auto surface = session->get_surface(surf_id);
2080+
2081+ advance_buffer(surf_id, *surface,
2082+ [lock, this, response, done, session](graphics::Buffer* client_buffer, bool need_full_ipc)
2083+ {
2084+ lock->unlock();
2085+
2086+ pack_protobuf_buffer(*response, client_buffer, need_full_ipc);
2087+
2088+ done->Run();
2089+ });
2090 }
2091
2092 void mf::SessionMediator::release_surface(
2093@@ -340,6 +350,59 @@
2094 done->Run();
2095 }
2096
2097+void mf::SessionMediator::create_screencast(
2098+ google::protobuf::RpcController*,
2099+ const mir::protobuf::ScreencastParameters* parameters,
2100+ mir::protobuf::Screencast* protobuf_screencast,
2101+ google::protobuf::Closure* done)
2102+{
2103+ static bool const need_full_ipc{true};
2104+ mg::DisplayConfigurationOutputId const output_id{
2105+ static_cast<int>(parameters->output_id())};
2106+
2107+ auto screencast_session_id = screencast->create_session(output_id);
2108+ auto buffer = screencast->capture(screencast_session_id);
2109+
2110+ protobuf_screencast->mutable_screencast_id()->set_value(
2111+ screencast_session_id.as_value());
2112+ pack_protobuf_buffer(*protobuf_screencast->mutable_buffer(),
2113+ buffer.get(),
2114+ need_full_ipc);
2115+
2116+ done->Run();
2117+}
2118+
2119+void mf::SessionMediator::release_screencast(
2120+ google::protobuf::RpcController*,
2121+ const mir::protobuf::ScreencastId* protobuf_screencast_id,
2122+ mir::protobuf::Void*,
2123+ google::protobuf::Closure* done)
2124+{
2125+ ScreencastSessionId const screencast_session_id{
2126+ protobuf_screencast_id->value()};
2127+ screencast->destroy_session(screencast_session_id);
2128+ done->Run();
2129+}
2130+
2131+void mf::SessionMediator::screencast_buffer(
2132+ google::protobuf::RpcController*,
2133+ const mir::protobuf::ScreencastId* protobuf_screencast_id,
2134+ mir::protobuf::Buffer* protobuf_buffer,
2135+ google::protobuf::Closure* done)
2136+{
2137+ static bool const does_not_need_full_ipc{false};
2138+ ScreencastSessionId const screencast_session_id{
2139+ protobuf_screencast_id->value()};
2140+
2141+ auto buffer = screencast->capture(screencast_session_id);
2142+
2143+ pack_protobuf_buffer(*protobuf_buffer,
2144+ buffer.get(),
2145+ does_not_need_full_ipc);
2146+
2147+ done->Run();
2148+}
2149+
2150 void mf::SessionMediator::pack_protobuf_buffer(
2151 protobuf::Buffer& protobuf_buffer,
2152 graphics::Buffer* graphics_buffer,
2153
2154=== modified file 'src/server/frontend/session_mediator.h'
2155--- src/server/frontend/session_mediator.h 2014-01-13 06:12:33 +0000
2156+++ src/server/frontend/session_mediator.h 2014-02-10 09:00:06 +0000
2157@@ -1,5 +1,5 @@
2158 /*
2159- * Copyright © 2012 Canonical Ltd.
2160+ * Copyright © 2012-2014 Canonical Ltd.
2161 *
2162 * This program is free software: you can redistribute it and/or modify it
2163 * under the terms of the GNU General Public License version 3,
2164@@ -24,6 +24,7 @@
2165 #include "mir/frontend/surface_id.h"
2166 #include "mir_toolkit/common.h"
2167
2168+#include <functional>
2169 #include <unordered_map>
2170 #include <memory>
2171 #include <mutex>
2172@@ -52,19 +53,22 @@
2173 class SessionMediatorReport;
2174 class EventSink;
2175 class DisplayChanger;
2176+class Screencast;
2177
2178 // SessionMediator relays requests from the client process into the server.
2179 class SessionMediator : public mir::protobuf::DisplayServer
2180 {
2181 public:
2182 SessionMediator(
2183+ pid_t client_pid,
2184 std::shared_ptr<Shell> const& shell,
2185 std::shared_ptr<graphics::Platform> const& graphics_platform,
2186 std::shared_ptr<frontend::DisplayChanger> const& display_changer,
2187 std::vector<MirPixelFormat> const& surface_pixel_formats,
2188 std::shared_ptr<SessionMediatorReport> const& report,
2189 std::shared_ptr<EventSink> const& event_sink,
2190- std::shared_ptr<ResourceCache> const& resource_cache);
2191+ std::shared_ptr<ResourceCache> const& resource_cache,
2192+ std::shared_ptr<Screencast> const& screencast);
2193
2194 ~SessionMediator() noexcept;
2195
2196@@ -105,6 +109,21 @@
2197 ::mir::protobuf::DisplayConfiguration* response,
2198 ::google::protobuf::Closure* done) override;
2199
2200+ void create_screencast(google::protobuf::RpcController*,
2201+ const mir::protobuf::ScreencastParameters*,
2202+ mir::protobuf::Screencast*,
2203+ google::protobuf::Closure* done);
2204+
2205+ void release_screencast(google::protobuf::RpcController*,
2206+ const mir::protobuf::ScreencastId*,
2207+ mir::protobuf::Void*,
2208+ google::protobuf::Closure* done);
2209+
2210+ void screencast_buffer(google::protobuf::RpcController*,
2211+ const mir::protobuf::ScreencastId*,
2212+ mir::protobuf::Buffer*,
2213+ google::protobuf::Closure* done);
2214+
2215 /* Platform specific requests */
2216 void drm_auth_magic(google::protobuf::RpcController* controller,
2217 const mir::protobuf::DRMMagic* request,
2218@@ -116,7 +135,8 @@
2219 graphics::Buffer* graphics_buffer,
2220 bool need_full_ipc);
2221
2222- std::tuple<graphics::Buffer*, bool> advance_buffer(SurfaceId surf_id, Surface& surface);
2223+ void advance_buffer(SurfaceId surf_id, Surface& surface, std::function<void(graphics::Buffer*, bool)> complete);
2224+ pid_t client_pid;
2225 std::shared_ptr<Shell> const shell;
2226 std::shared_ptr<graphics::Platform> const graphics_platform;
2227
2228@@ -126,6 +146,7 @@
2229 std::shared_ptr<SessionMediatorReport> const report;
2230 std::shared_ptr<EventSink> const event_sink;
2231 std::shared_ptr<ResourceCache> const resource_cache;
2232+ std::shared_ptr<Screencast> const screencast;
2233
2234 std::unordered_map<SurfaceId,graphics::Buffer*> client_buffer_resource;
2235 std::unordered_map<SurfaceId, std::shared_ptr<ClientBufferTracker>> client_buffer_tracker;
2236
2237=== modified file 'src/server/frontend/surface.cpp'
2238--- src/server/frontend/surface.cpp 2014-01-13 06:12:33 +0000
2239+++ src/server/frontend/surface.cpp 2014-02-10 09:00:06 +0000
2240@@ -25,6 +25,10 @@
2241
2242 #include "client_buffer_tracker.h"
2243
2244+#include <condition_variable>
2245+#include <mutex>
2246+#include <thread>
2247+
2248 namespace mg = mir::graphics;
2249 namespace mf = mir::frontend;
2250
2251@@ -39,7 +43,7 @@
2252 private:
2253 void swap_buffers(graphics::Buffer*& buffer)
2254 {
2255- surface->swap_buffers(buffer);
2256+ surface->swap_buffers_blocking(buffer);
2257 }
2258 virtual mir::geometry::Size size() const { return surface->size(); }
2259 virtual MirPixelFormat pixel_format() const { return surface->pixel_format(); }
2260@@ -49,3 +53,23 @@
2261
2262 return std::make_shared<ForwardingInternalSurface>(surface);
2263 }
2264+
2265+void mf::Surface::swap_buffers_blocking(graphics::Buffer*& buffer)
2266+{
2267+ std::mutex mutex;
2268+ std::condition_variable cv;
2269+ bool done = false;
2270+
2271+ swap_buffers(buffer,
2272+ [&](mg::Buffer* new_buffer)
2273+ {
2274+ std::unique_lock<decltype(mutex)> lock(mutex);
2275+ buffer = new_buffer;
2276+ done = true;
2277+ cv.notify_one();
2278+ });
2279+
2280+ std::unique_lock<decltype(mutex)> lock(mutex);
2281+
2282+ cv.wait(lock, [&]{ return done; });
2283+}
2284
2285=== modified file 'src/server/graphics/nested/nested_display.cpp'
2286--- src/server/graphics/nested/nested_display.cpp 2014-01-13 06:12:33 +0000
2287+++ src/server/graphics/nested/nested_display.cpp 2014-02-10 09:00:06 +0000
2288@@ -152,9 +152,13 @@
2289 f(*i.second);
2290 }
2291
2292-std::shared_ptr<mg::DisplayConfiguration> mgn::NestedDisplay::configuration()
2293+std::unique_ptr<mg::DisplayConfiguration> mgn::NestedDisplay::configuration() const
2294 {
2295- return std::make_shared<NestedDisplayConfiguration>(mir_connection_create_display_config(*connection));
2296+ return std::unique_ptr<mg::DisplayConfiguration>(
2297+ new NestedDisplayConfiguration(
2298+ mir_connection_create_display_config(*connection)
2299+ )
2300+ );
2301 }
2302
2303 void mgn::NestedDisplay::complete_display_initialization(MirPixelFormat format)
2304
2305=== modified file 'src/server/graphics/nested/nested_display.h'
2306--- src/server/graphics/nested/nested_display.h 2014-01-13 06:12:33 +0000
2307+++ src/server/graphics/nested/nested_display.h 2014-02-10 09:00:06 +0000
2308@@ -102,7 +102,7 @@
2309
2310 void for_each_display_buffer(std::function<void(DisplayBuffer&)>const& f) override;
2311
2312- std::shared_ptr<DisplayConfiguration> configuration() override;
2313+ std::unique_ptr<DisplayConfiguration> configuration() const override;
2314 void configure(DisplayConfiguration const&) override;
2315
2316 void register_configuration_change_handler(
2317
2318=== modified file 'src/server/graphics/offscreen/display.cpp'
2319--- src/server/graphics/offscreen/display.cpp 2014-01-10 08:51:30 +0000
2320+++ src/server/graphics/offscreen/display.cpp 2014-02-10 09:00:06 +0000
2321@@ -108,10 +108,12 @@
2322 f(*db_ptr);
2323 }
2324
2325-std::shared_ptr<mg::DisplayConfiguration> mgo::Display::configuration()
2326+std::unique_ptr<mg::DisplayConfiguration> mgo::Display::configuration() const
2327 {
2328 std::lock_guard<std::mutex> lock{configuration_mutex};
2329- return std::make_shared<mgo::DisplayConfiguration>(current_display_configuration);
2330+ return std::unique_ptr<mg::DisplayConfiguration>(
2331+ new mgo::DisplayConfiguration(current_display_configuration)
2332+ );
2333 }
2334
2335 void mgo::Display::configure(mg::DisplayConfiguration const& conf)
2336
2337=== modified file 'src/server/graphics/offscreen/display.h'
2338--- src/server/graphics/offscreen/display.h 2013-12-13 05:24:22 +0000
2339+++ src/server/graphics/offscreen/display.h 2014-02-10 09:00:06 +0000
2340@@ -71,8 +71,8 @@
2341
2342 void for_each_display_buffer(std::function<void(DisplayBuffer&)> const& f);
2343
2344- std::shared_ptr<graphics::DisplayConfiguration> configuration();
2345- void configure(graphics::DisplayConfiguration const& conf);
2346+ std::unique_ptr<graphics::DisplayConfiguration> configuration() const override;
2347+ void configure(graphics::DisplayConfiguration const& conf) override;
2348
2349 void register_configuration_change_handler(
2350 EventHandlerRegister& handlers,
2351@@ -93,7 +93,7 @@
2352 std::shared_ptr<BasicPlatform> const basic_platform;
2353 detail::EGLDisplayHandle const egl_display;
2354 SurfacelessEGLContext const egl_context_shared;
2355- std::mutex configuration_mutex;
2356+ mutable std::mutex configuration_mutex;
2357 DisplayConfiguration current_display_configuration;
2358 std::vector<std::unique_ptr<DisplayBuffer>> display_buffers;
2359 };
2360
2361=== modified file 'src/server/scene/application_session.cpp'
2362--- src/server/scene/application_session.cpp 2014-01-13 06:12:33 +0000
2363+++ src/server/scene/application_session.cpp 2014-02-10 09:00:06 +0000
2364@@ -1,5 +1,5 @@
2365 /*
2366- * Copyright © 2012 Canonical Ltd.
2367+ * Copyright © 2012-2014 Canonical Ltd.
2368 *
2369 * This program is free software: you can redistribute it and/or modify it
2370 * under the terms of the GNU General Public License version 3,
2371@@ -37,11 +37,13 @@
2372
2373 ms::ApplicationSession::ApplicationSession(
2374 std::shared_ptr<msh::SurfaceFactory> const& surface_factory,
2375+ pid_t pid,
2376 std::string const& session_name,
2377 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
2378 std::shared_ptr<msh::SessionListener> const& session_listener,
2379 std::shared_ptr<mf::EventSink> const& sink) :
2380 surface_factory(surface_factory),
2381+ pid(pid),
2382 session_name(session_name),
2383 snapshot_strategy(snapshot_strategy),
2384 session_listener(session_listener),
2385@@ -125,6 +127,11 @@
2386 return session_name;
2387 }
2388
2389+pid_t ms::ApplicationSession::process_id() const
2390+{
2391+ return pid;
2392+}
2393+
2394 void ms::ApplicationSession::force_requests_to_complete()
2395 {
2396 std::unique_lock<std::mutex> lock(surfaces_mutex);
2397
2398=== modified file 'src/server/scene/application_session.h'
2399--- src/server/scene/application_session.h 2014-01-13 06:12:33 +0000
2400+++ src/server/scene/application_session.h 2014-02-10 09:00:06 +0000
2401@@ -1,5 +1,5 @@
2402 /*
2403- * Copyright © 2013 Canonical Ltd.
2404+ * Copyright © 2013-2014 Canonical Ltd.
2405 *
2406 * This program is free software: you can redistribute it and/or modify it
2407 * under the terms of the GNU General Public License version 3,
2408@@ -45,6 +45,7 @@
2409 public:
2410 ApplicationSession(
2411 std::shared_ptr<shell::SurfaceFactory> const& surface_factory,
2412+ pid_t pid,
2413 std::string const& session_name,
2414 std::shared_ptr<SnapshotStrategy> const& snapshot_strategy,
2415 std::shared_ptr<shell::SessionListener> const& session_listener,
2416@@ -60,6 +61,7 @@
2417 std::shared_ptr<shell::Surface> default_surface() const;
2418
2419 std::string name() const;
2420+ pid_t process_id() const override;
2421
2422 void force_requests_to_complete();
2423
2424@@ -77,6 +79,7 @@
2425
2426 private:
2427 std::shared_ptr<shell::SurfaceFactory> const surface_factory;
2428+ pid_t const pid;
2429 std::string const session_name;
2430 std::shared_ptr<SnapshotStrategy> const snapshot_strategy;
2431 std::shared_ptr<shell::SessionListener> const session_listener;
2432
2433=== modified file 'src/server/scene/basic_surface.cpp'
2434--- src/server/scene/basic_surface.cpp 2014-01-24 08:29:36 +0000
2435+++ src/server/scene/basic_surface.cpp 2014-02-10 09:00:06 +0000
2436@@ -114,11 +114,11 @@
2437 return surface_buffer_stream->get_stream_pixel_format();
2438 }
2439
2440-void ms::BasicSurface::swap_buffers(graphics::Buffer*& buffer)
2441+void ms::BasicSurface::swap_buffers(mg::Buffer* old_buffer, std::function<void(mg::Buffer* new_buffer)> complete)
2442 {
2443- bool const posting{!!buffer};
2444+ bool const posting{!!old_buffer};
2445
2446- surface_buffer_stream->swap_client_buffers(buffer);
2447+ surface_buffer_stream->swap_client_buffers(old_buffer, complete);
2448
2449 if (posting)
2450 {
2451
2452=== modified file 'src/server/scene/basic_surface.h'
2453--- src/server/scene/basic_surface.h 2014-01-24 08:29:36 +0000
2454+++ src/server/scene/basic_surface.h 2014-02-10 09:00:06 +0000
2455@@ -73,7 +73,7 @@
2456 virtual MirPixelFormat pixel_format() const;
2457
2458 virtual std::shared_ptr<graphics::Buffer> snapshot_buffer() const;
2459- virtual void swap_buffers(graphics::Buffer*&);
2460+ virtual void swap_buffers(graphics::Buffer* old_buffer, std::function<void(graphics::Buffer* new_buffer)> complete);
2461 virtual void force_requests_to_complete();
2462
2463 virtual bool supports_input() const;
2464
2465=== modified file 'src/server/scene/session_manager.cpp'
2466--- src/server/scene/session_manager.cpp 2014-01-13 06:12:33 +0000
2467+++ src/server/scene/session_manager.cpp 2014-02-10 09:00:06 +0000
2468@@ -1,5 +1,5 @@
2469 /*
2470- * Copyright © 2012 Canonical Ltd.
2471+ * Copyright © 2012-2014 Canonical Ltd.
2472 *
2473 * This program is free software: you can redistribute it and/or modify it
2474 * under the terms of the GNU General Public License version 3,
2475@@ -73,12 +73,14 @@
2476 close_session(session);
2477 }
2478
2479-std::shared_ptr<mf::Session> ms::SessionManager::open_session(std::string const& name,
2480- std::shared_ptr<mf::EventSink> const& sender)
2481+std::shared_ptr<mf::Session> ms::SessionManager::open_session(
2482+ pid_t client_pid,
2483+ std::string const& name,
2484+ std::shared_ptr<mf::EventSink> const& sender)
2485 {
2486 std::shared_ptr<msh::Session> new_session =
2487 std::make_shared<ApplicationSession>(
2488- surface_factory, name, snapshot_strategy, session_listener, sender);
2489+ surface_factory, client_pid, name, snapshot_strategy, session_listener, sender);
2490
2491 app_container->insert_session(new_session);
2492
2493
2494=== modified file 'src/server/scene/session_manager.h'
2495--- src/server/scene/session_manager.h 2014-01-13 06:12:33 +0000
2496+++ src/server/scene/session_manager.h 2014-02-10 09:00:06 +0000
2497@@ -1,5 +1,5 @@
2498 /*
2499- * Copyright © 2012 Canonical Ltd.
2500+ * Copyright © 2012-2014 Canonical Ltd.
2501 *
2502 * This program is free software: you can redistribute it and/or modify it
2503 * under the terms of the GNU General Public License version 3,
2504@@ -55,7 +55,10 @@
2505 virtual ~SessionManager();
2506
2507 virtual std::shared_ptr<frontend::Session> open_session(
2508- std::string const& name, std::shared_ptr<frontend::EventSink> const& sink);
2509+ pid_t client_pid,
2510+ std::string const& name,
2511+ std::shared_ptr<frontend::EventSink> const& sink);
2512+
2513 virtual void close_session(std::shared_ptr<frontend::Session> const& session);
2514
2515 frontend::SurfaceId create_surface_for(std::shared_ptr<frontend::Session> const& session,
2516
2517=== modified file 'src/server/scene/surface_impl.cpp'
2518--- src/server/scene/surface_impl.cpp 2014-01-24 08:29:36 +0000
2519+++ src/server/scene/surface_impl.cpp 2014-02-10 09:00:06 +0000
2520@@ -103,9 +103,9 @@
2521 return surface->pixel_format();
2522 }
2523
2524-void ms::SurfaceImpl::swap_buffers(graphics::Buffer*& buffer)
2525+void ms::SurfaceImpl::swap_buffers(mg::Buffer* old_buffer, std::function<void(mg::Buffer* new_buffer)> complete)
2526 {
2527- surface->swap_buffers(buffer);
2528+ surface->swap_buffers(old_buffer, complete);
2529 }
2530
2531 void ms::SurfaceImpl::allow_framedropping(bool allow)
2532
2533=== modified file 'src/server/scene/surface_impl.h'
2534--- src/server/scene/surface_impl.h 2014-01-13 06:12:33 +0000
2535+++ src/server/scene/surface_impl.h 2014-02-10 09:00:06 +0000
2536@@ -70,7 +70,7 @@
2537
2538 virtual void with_most_recent_buffer_do(
2539 std::function<void(graphics::Buffer&)> const& exec);
2540- virtual void swap_buffers(graphics::Buffer*& buffer);
2541+ virtual void swap_buffers(graphics::Buffer* old_buffer, std::function<void(graphics::Buffer* new_buffer)> complete) override;
2542
2543 virtual bool supports_input() const;
2544 virtual int client_input_fd() const;
2545
2546=== modified file 'src/utils/CMakeLists.txt'
2547--- src/utils/CMakeLists.txt 2014-01-10 05:48:41 +0000
2548+++ src/utils/CMakeLists.txt 2014-02-10 09:00:06 +0000
2549@@ -13,8 +13,17 @@
2550 add_executable(mirout out.c)
2551 target_link_libraries(mirout mirclient)
2552
2553+add_executable(mirscreencast screencast.cpp)
2554+
2555+target_link_libraries(mirscreencast
2556+ mirclient
2557+ ${EGL_LIBRARIES}
2558+ ${GLESv2_LIBRARIES}
2559+)
2560+
2561 install(TARGETS
2562 mirping
2563 mirout
2564+ mirscreencast
2565 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
2566 )
2567
2568=== added file 'src/utils/screencast.cpp'
2569--- src/utils/screencast.cpp 1970-01-01 00:00:00 +0000
2570+++ src/utils/screencast.cpp 2014-02-10 09:00:06 +0000
2571@@ -0,0 +1,313 @@
2572+/*
2573+ * Copyright © 2014 Canonical Ltd.
2574+ *
2575+ * This program is free software: you can redistribute it and/or modify
2576+ * it under the terms of the GNU General Public License version 3 as
2577+ * published by the Free Software Foundation.
2578+ *
2579+ * This program is distributed in the hope that it will be useful,
2580+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2581+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2582+ * GNU General Public License for more details.
2583+ *
2584+ * You should have received a copy of the GNU General Public License
2585+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2586+ *
2587+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
2588+ */
2589+
2590+#include "mir_toolkit/mir_client_library.h"
2591+#include "mir_toolkit/mir_screencast.h"
2592+#include "mir/geometry/size.h"
2593+
2594+#include "mir/raii.h"
2595+
2596+#include <getopt.h>
2597+#include <csignal>
2598+
2599+#include <EGL/egl.h>
2600+#include <GLES2/gl2.h>
2601+#include <GLES2/gl2ext.h>
2602+
2603+#include <fstream>
2604+#include <sstream>
2605+#include <thread>
2606+#include <iostream>
2607+#include <stdexcept>
2608+#include <future>
2609+#include <vector>
2610+
2611+namespace
2612+{
2613+
2614+volatile sig_atomic_t running = 1;
2615+
2616+void shutdown(int)
2617+{
2618+ running = 0;
2619+}
2620+
2621+std::future<void> write_frame_to_file(
2622+ std::vector<char> const& frame_data, int frame_number, GLenum format)
2623+{
2624+ return std::async(
2625+ std::launch::async,
2626+ [&frame_data, frame_number, format]
2627+ {
2628+ std::stringstream ss;
2629+ ss << "/tmp/mir_" ;
2630+ ss.width(5);
2631+ ss.fill('0');
2632+ ss << frame_number;
2633+ ss << (format == GL_BGRA_EXT ? ".bgra" : ".rgba");
2634+ std::ofstream f(ss.str());
2635+ f.write(frame_data.data(), frame_data.size());
2636+ });
2637+}
2638+
2639+GLenum read_pixels(mir::geometry::Size const& size, void* buffer)
2640+{
2641+ auto width = size.width.as_uint32_t();
2642+ auto height = size.height.as_uint32_t();
2643+
2644+ GLenum format = GL_BGRA_EXT;
2645+
2646+ glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, buffer);
2647+
2648+ if (glGetError() != GL_NO_ERROR)
2649+ {
2650+ format = GL_RGBA;
2651+ glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, buffer);
2652+ }
2653+
2654+ return format;
2655+}
2656+
2657+
2658+uint32_t get_first_valid_output_id(MirConnection* connection)
2659+{
2660+ auto const conf = mir::raii::deleter_for(
2661+ mir_connection_create_display_config(connection),
2662+ &mir_display_config_destroy);
2663+
2664+ if (conf == nullptr)
2665+ throw std::runtime_error("Failed to get display configuration\n");
2666+
2667+ for (unsigned i = 0; i < conf->num_outputs; ++i)
2668+ {
2669+ MirDisplayOutput const& output = conf->outputs[i];
2670+
2671+ if (output.connected && output.used &&
2672+ output.current_mode < output.num_modes)
2673+ {
2674+ return output.output_id;
2675+ }
2676+ }
2677+
2678+ throw std::runtime_error("Couldn't find a valid output to screencast");
2679+}
2680+
2681+mir::geometry::Size get_output_size(MirConnection* connection, uint32_t output_id)
2682+{
2683+ auto const conf = mir::raii::deleter_for(
2684+ mir_connection_create_display_config(connection),
2685+ &mir_display_config_destroy);
2686+
2687+ if (conf == nullptr)
2688+ throw std::runtime_error("Failed to get display configuration\n");
2689+
2690+ for (unsigned i = 0; i < conf->num_outputs; ++i)
2691+ {
2692+ MirDisplayOutput const& output = conf->outputs[i];
2693+
2694+ if (output.output_id == output_id &&
2695+ output.current_mode < output.num_modes)
2696+ {
2697+ MirDisplayMode const& mode = output.modes[output.current_mode];
2698+ return mir::geometry::Size{mode.horizontal_resolution, mode.vertical_resolution};
2699+ }
2700+ }
2701+
2702+ throw std::runtime_error("Couldn't get size of specified output");
2703+}
2704+
2705+void print_usage()
2706+{
2707+ std::cout << "Usage " << std::endl
2708+ << " -m <Mir server socket>" << std::endl
2709+ << " -o <Output id>" << std::endl
2710+ << " -h: this help text" << std::endl;
2711+}
2712+
2713+struct EGLSetup
2714+{
2715+ EGLSetup(MirConnection* connection, MirScreencast* screencast)
2716+ {
2717+ static EGLint const attribs[] = {
2718+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
2719+ EGL_RED_SIZE, 8,
2720+ EGL_GREEN_SIZE, 8,
2721+ EGL_BLUE_SIZE, 8,
2722+ EGL_ALPHA_SIZE, 8,
2723+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
2724+ EGL_NONE};
2725+
2726+ static EGLint const context_attribs[] = {
2727+ EGL_CONTEXT_CLIENT_VERSION, 2,
2728+ EGL_NONE };
2729+
2730+ auto native_display =
2731+ reinterpret_cast<EGLNativeDisplayType>(
2732+ mir_connection_get_egl_native_display(connection));
2733+
2734+ auto native_window =
2735+ reinterpret_cast<EGLNativeWindowType>(
2736+ mir_screencast_egl_native_window(screencast));
2737+
2738+ egl_display = eglGetDisplay(native_display);
2739+
2740+ eglInitialize(egl_display, nullptr, nullptr);
2741+
2742+ int n;
2743+ eglChooseConfig(egl_display, attribs, &egl_config, 1, &n);
2744+
2745+ egl_surface = eglCreateWindowSurface(egl_display, egl_config, native_window, NULL);
2746+ if (egl_surface == EGL_NO_SURFACE)
2747+ throw std::runtime_error("Failed to create EGL screencast surface");
2748+
2749+ egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs);
2750+ if (egl_context == EGL_NO_CONTEXT)
2751+ throw std::runtime_error("Failed to create EGL context for screencast");
2752+
2753+ if (eglMakeCurrent(egl_display, egl_surface,
2754+ egl_surface, egl_context) != EGL_TRUE)
2755+ {
2756+ throw std::runtime_error("Failed to make screencast surface current");
2757+ }
2758+ }
2759+
2760+ ~EGLSetup()
2761+ {
2762+ eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
2763+ eglDestroySurface(egl_display, egl_surface);
2764+ eglDestroyContext(egl_display, egl_context);
2765+ eglTerminate(egl_display);
2766+ }
2767+
2768+ void swap_buffers()
2769+ {
2770+ if (eglSwapBuffers(egl_display, egl_surface) != EGL_TRUE)
2771+ throw std::runtime_error("Failed to swap screencast surface buffers");
2772+ }
2773+
2774+ EGLDisplay egl_display;
2775+ EGLContext egl_context;
2776+ EGLSurface egl_surface;
2777+ EGLConfig egl_config;
2778+};
2779+
2780+void do_screencast(MirConnection* connection, MirScreencast* screencast,
2781+ uint32_t output_id)
2782+{
2783+ static int const rgba_pixel_size{4};
2784+
2785+ auto const frame_size = get_output_size(connection, output_id);
2786+ auto const frame_size_bytes = rgba_pixel_size *
2787+ frame_size.width.as_uint32_t() *
2788+ frame_size.height.as_uint32_t();
2789+
2790+ int frame_number{0};
2791+ std::vector<char> frame_data(frame_size_bytes, 0);
2792+ std::future<void> frame_written_future =
2793+ std::async(std::launch::deferred, []{});
2794+
2795+ EGLSetup egl_setup{connection, screencast};
2796+
2797+ while (running)
2798+ {
2799+ frame_written_future.wait();
2800+
2801+ auto format = read_pixels(frame_size, frame_data.data());
2802+ frame_written_future = write_frame_to_file(frame_data, frame_number, format);
2803+
2804+ egl_setup.swap_buffers();
2805+ ++frame_number;
2806+ }
2807+}
2808+
2809+}
2810+
2811+int main(int argc, char* argv[])
2812+try
2813+{
2814+ int arg;
2815+ opterr = 0;
2816+ char const* socket_file = nullptr;
2817+ uint32_t output_id = mir_display_output_id_invalid;
2818+
2819+ while ((arg = getopt (argc, argv, "hm:o:")) != -1)
2820+ {
2821+ switch (arg)
2822+ {
2823+ case 'm':
2824+ socket_file = optarg;
2825+ break;
2826+
2827+ case 'o':
2828+ output_id = std::stoul(optarg);
2829+ break;
2830+
2831+ case '?':
2832+ case 'h':
2833+ print_usage();
2834+ return EXIT_SUCCESS;
2835+
2836+ default:
2837+ print_usage();
2838+ return EXIT_FAILURE;
2839+ }
2840+ }
2841+
2842+ signal(SIGINT, shutdown);
2843+ signal(SIGTERM, shutdown);
2844+
2845+ auto const connection = mir::raii::deleter_for(
2846+ mir_connect_sync(socket_file, "mirscreencast"),
2847+ [](MirConnection* c) { if (c) mir_connection_release(c); });
2848+
2849+ if (connection == nullptr || !mir_connection_is_valid(connection.get()))
2850+ {
2851+ std::string msg("Failed to connect to server.");
2852+ if (connection)
2853+ {
2854+ msg += " Error was :";
2855+ msg += mir_connection_get_error_message(connection.get());
2856+ }
2857+ throw std::runtime_error(std::string(msg));
2858+ }
2859+
2860+ if (output_id == mir_display_output_id_invalid)
2861+ output_id = get_first_valid_output_id(connection.get());
2862+
2863+ MirScreencastParameters params{
2864+ output_id, 0, 0, mir_pixel_format_invalid};
2865+
2866+ std::cout << "Starting screencast for output id " << params.output_id << std::endl;
2867+
2868+ auto const screencast = mir::raii::deleter_for(
2869+ mir_connection_create_screencast_sync(connection.get(), &params),
2870+ [](MirScreencast* s) { if (s) mir_screencast_release_sync(s); });
2871+
2872+ if (screencast == nullptr)
2873+ throw std::runtime_error("Failed to create screencast");
2874+
2875+ do_screencast(connection.get(), screencast.get(), output_id);
2876+
2877+ return EXIT_SUCCESS;
2878+}
2879+catch(std::exception const& e)
2880+{
2881+ std::cerr << e.what() << std::endl;
2882+
2883+ return EXIT_FAILURE;
2884+}
2885
2886=== modified file 'tests/acceptance-tests/test_client_screencast.cpp'
2887--- tests/acceptance-tests/test_client_screencast.cpp 2014-01-29 17:20:51 +0000
2888+++ tests/acceptance-tests/test_client_screencast.cpp 2014-02-10 09:00:06 +0000
2889@@ -22,11 +22,11 @@
2890 #include "mir_test_framework/stubbed_server_configuration.h"
2891 #include "mir_test_framework/in_process_server.h"
2892 #include "mir_test_framework/using_stub_client_platform.h"
2893-#include "src/server/frontend/protobuf_ipc_factory.h"
2894-#include "mir_protobuf.pb.h"
2895
2896 #include "mir_test_doubles/null_display_changer.h"
2897 #include "mir_test_doubles/stub_display_configuration.h"
2898+#include "mir_test_doubles/stub_buffer.h"
2899+#include "mir_test_doubles/mock_screencast.h"
2900 #include "mir_test/fake_shared.h"
2901
2902 #include <gtest/gtest.h>
2903@@ -41,114 +41,6 @@
2904 namespace
2905 {
2906
2907-ACTION(RunClosure)
2908-{
2909- arg3->Run();
2910-}
2911-
2912-MATCHER_P(WithOutputId, value, "")
2913-{
2914- return arg->output_id() == value;
2915-}
2916-
2917-MATCHER_P(WithScreencastId, value, "")
2918-{
2919- return arg->value() == value;
2920-}
2921-
2922-ACTION_P(SetCreateScreencastId, screencast_id)
2923-{
2924- arg2->mutable_screencast_id()->set_value(screencast_id);
2925-}
2926-
2927-ACTION(FillCreateScreencastBuffer)
2928-{
2929- int fds[2]{-1,-1};
2930- if (pipe(fds))
2931- FAIL() << "Failed to create FillCreateScreencastBuffer fds";
2932- close(fds[1]);
2933- arg2->mutable_buffer()->add_fd(fds[0]);
2934-}
2935-
2936-/*
2937- * This setup is used temporarily to test MirScreencast, until
2938- * we have the server-side implementation of the feature in place.
2939- */
2940-struct MockScreencastServer : mir::protobuf::DisplayServer
2941-{
2942- MockScreencastServer(
2943- std::shared_ptr<mir::protobuf::DisplayServer> const& ds)
2944- : wrapped_display_server{ds}
2945- {
2946- using namespace testing;
2947- ON_CALL(*this, create_screencast(_,_,_,_))
2948- .WillByDefault(DoAll(FillCreateScreencastBuffer(),RunClosure()));
2949- ON_CALL(*this, release_screencast(_,_,_,_))
2950- .WillByDefault(RunClosure());
2951- }
2952-
2953- void connect(
2954- ::google::protobuf::RpcController* rpc,
2955- const ::mir::protobuf::ConnectParameters* request,
2956- ::mir::protobuf::Connection* response,
2957- ::google::protobuf::Closure* done) override
2958- {
2959- wrapped_display_server->connect(rpc, request, response, done);
2960- }
2961-
2962- void disconnect(
2963- google::protobuf::RpcController* rpc,
2964- const mir::protobuf::Void* request,
2965- mir::protobuf::Void* response,
2966- google::protobuf::Closure* done) override
2967- {
2968- wrapped_display_server->disconnect(rpc, request, response, done);
2969- }
2970-
2971- MOCK_METHOD4(create_screencast,
2972- void(google::protobuf::RpcController*,
2973- const mir::protobuf::ScreencastParameters*,
2974- mir::protobuf::Screencast*,
2975- google::protobuf::Closure*));
2976-
2977- MOCK_METHOD4(release_screencast,
2978- void(google::protobuf::RpcController*,
2979- const mir::protobuf::ScreencastId*,
2980- mir::protobuf::Void*,
2981- google::protobuf::Closure*));
2982-
2983- std::shared_ptr<mir::protobuf::DisplayServer> const wrapped_display_server;
2984-};
2985-
2986-std::shared_ptr<MockScreencastServer> global_mock_screencast_server;
2987-
2988-class WrappingIpcFactory : public mf::ProtobufIpcFactory
2989-{
2990-public:
2991- WrappingIpcFactory(
2992- std::shared_ptr<mf::ProtobufIpcFactory> const& ipc_factory)
2993- : wrapped_ipc_factory{ipc_factory}
2994- {
2995- }
2996-
2997- std::shared_ptr<mir::protobuf::DisplayServer> make_ipc_server(
2998- std::shared_ptr<mf::EventSink> const& sink, bool auth) override
2999- {
3000- auto ipc_server = wrapped_ipc_factory->make_ipc_server(sink, auth);
3001- global_mock_screencast_server =
3002- std::make_shared<testing::NiceMock<MockScreencastServer>>(ipc_server);
3003- return global_mock_screencast_server;
3004- }
3005-
3006- std::shared_ptr<mf::ResourceCache> resource_cache() override
3007- {
3008- return wrapped_ipc_factory->resource_cache();
3009- }
3010-
3011-private:
3012- std::shared_ptr<mf::ProtobufIpcFactory> const wrapped_ipc_factory;
3013-};
3014-
3015 class StubChanger : public mtd::NullDisplayChanger
3016 {
3017 public:
3018@@ -179,27 +71,22 @@
3019 return mt::fake_shared(stub_changer);
3020 }
3021
3022- std::shared_ptr<mf::ProtobufIpcFactory> the_ipc_factory(
3023- std::shared_ptr<mf::Shell> const& shell,
3024- std::shared_ptr<mg::GraphicBufferAllocator> const& alloc) override
3025+ std::shared_ptr<mf::Screencast> the_screencast() override
3026 {
3027- auto factory = mtf::StubbedServerConfiguration::the_ipc_factory(shell, alloc);
3028- return std::make_shared<WrappingIpcFactory>(factory);
3029+ return mt::fake_shared(mock_screencast);
3030 }
3031
3032 StubChanger stub_changer;
3033+ mtd::MockScreencast mock_screencast;
3034 };
3035
3036 class MirScreencastTest : public mir_test_framework::InProcessServer
3037 {
3038 public:
3039- ~MirScreencastTest()
3040- {
3041- global_mock_screencast_server.reset();
3042- }
3043-
3044 mir::DefaultServerConfiguration& server_config() override { return server_config_; }
3045
3046+ mtd::MockScreencast& mock_screencast() { return server_config_.mock_screencast; }
3047+
3048 StubServerConfig server_config_;
3049 mtf::UsingStubClientPlatform using_stub_client_platform;
3050 };
3051@@ -227,8 +114,7 @@
3052 uint32_t const invalid_output_id{33};
3053 MirScreencastParameters params{invalid_output_id, 0, 0, mir_pixel_format_invalid};
3054
3055- EXPECT_CALL(*global_mock_screencast_server,
3056- create_screencast(_,_,_,_))
3057+ EXPECT_CALL(mock_screencast(), create_session(_))
3058 .Times(0);
3059
3060 auto screencast =
3061@@ -238,28 +124,27 @@
3062 mir_connection_release(connection);
3063 }
3064
3065-TEST_F(MirScreencastTest, create_and_release_contact_server)
3066+TEST_F(MirScreencastTest, contacts_server_screencast_for_create_and_release)
3067 {
3068 using namespace testing;
3069
3070 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
3071 ASSERT_TRUE(mir_connection_is_valid(connection));
3072
3073- uint32_t const screencast_id{99};
3074+ mf::ScreencastSessionId const screencast_session_id{99};
3075 uint32_t const output_id{2};
3076 MirScreencastParameters params{output_id, 0, 0, mir_pixel_format_invalid};
3077
3078 InSequence seq;
3079
3080- EXPECT_CALL(*global_mock_screencast_server,
3081- create_screencast(_,WithOutputId(output_id),_,_))
3082- .WillOnce(DoAll(SetCreateScreencastId(screencast_id),
3083- FillCreateScreencastBuffer(),
3084- RunClosure()));
3085-
3086- EXPECT_CALL(*global_mock_screencast_server,
3087- release_screencast(_,WithScreencastId(screencast_id),_,_))
3088- .WillOnce(RunClosure());
3089+ EXPECT_CALL(mock_screencast(),
3090+ create_session(mg::DisplayConfigurationOutputId{output_id}))
3091+ .WillOnce(Return(screencast_session_id));
3092+
3093+ EXPECT_CALL(mock_screencast(), capture(screencast_session_id))
3094+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3095+
3096+ EXPECT_CALL(mock_screencast(), destroy_session(screencast_session_id));
3097
3098 auto screencast = mir_connection_create_screencast_sync(connection, &params);
3099 ASSERT_NE(nullptr, screencast);
3100@@ -275,9 +160,17 @@
3101 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
3102 ASSERT_TRUE(mir_connection_is_valid(connection));
3103
3104+ mf::ScreencastSessionId const screencast_session_id{99};
3105 uint32_t const output_id{2};
3106 MirScreencastParameters params{output_id, 0, 0, mir_pixel_format_invalid};
3107
3108+ InSequence seq;
3109+ EXPECT_CALL(mock_screencast(), create_session(_))
3110+ .WillOnce(Return(screencast_session_id));
3111+ EXPECT_CALL(mock_screencast(), capture(_))
3112+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3113+ EXPECT_CALL(mock_screencast(), destroy_session(_));
3114+
3115 auto screencast = mir_connection_create_screencast_sync(connection, &params);
3116 ASSERT_NE(nullptr, screencast);
3117
3118@@ -288,3 +181,22 @@
3119
3120 mir_connection_release(connection);
3121 }
3122+
3123+TEST_F(MirScreencastTest, fails_on_client_when_server_request_fails)
3124+{
3125+ using namespace testing;
3126+
3127+ auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
3128+ ASSERT_TRUE(mir_connection_is_valid(connection));
3129+
3130+ uint32_t const output_id{2};
3131+ MirScreencastParameters params{output_id, 0, 0, mir_pixel_format_invalid};
3132+
3133+ EXPECT_CALL(mock_screencast(), create_session(_))
3134+ .WillOnce(Throw(std::runtime_error("")));
3135+
3136+ auto screencast = mir_connection_create_screencast_sync(connection, &params);
3137+ ASSERT_EQ(nullptr, screencast);
3138+
3139+ mir_connection_release(connection);
3140+}
3141
3142=== modified file 'tests/acceptance-tests/test_display_configuration.cpp'
3143--- tests/acceptance-tests/test_display_configuration.cpp 2014-01-13 06:12:33 +0000
3144+++ tests/acceptance-tests/test_display_configuration.cpp 2014-02-10 09:00:06 +0000
3145@@ -87,9 +87,11 @@
3146 f(display_buffer);
3147 }
3148
3149- std::shared_ptr<mg::DisplayConfiguration> configuration()
3150+ std::unique_ptr<mg::DisplayConfiguration> configuration() const override
3151 {
3152- return config;
3153+ return std::unique_ptr<mg::DisplayConfiguration>(
3154+ new mtd::StubDisplayConfig(*config)
3155+ );
3156 }
3157
3158 void register_configuration_change_handler(
3159@@ -112,7 +114,7 @@
3160 MOCK_METHOD1(configure, void(mg::DisplayConfiguration const&));
3161
3162 void emit_configuration_change_event(
3163- std::shared_ptr<mg::DisplayConfiguration> const& new_config)
3164+ std::shared_ptr<mtd::StubDisplayConfig> const& new_config)
3165 {
3166 config = new_config;
3167 if (write(p.write_fd(), "a", 1)) {}
3168@@ -125,7 +127,7 @@
3169 }
3170
3171 private:
3172- std::shared_ptr<mg::DisplayConfiguration> config;
3173+ std::shared_ptr<mtd::StubDisplayConfig> config;
3174 mtd::NullDisplayBuffer display_buffer;
3175 mt::Pipe p;
3176 std::atomic<bool> handler_called;
3177
3178=== modified file 'tests/acceptance-tests/test_protobuf.cpp'
3179--- tests/acceptance-tests/test_protobuf.cpp 2014-01-21 12:49:00 +0000
3180+++ tests/acceptance-tests/test_protobuf.cpp 2014-02-10 09:00:06 +0000
3181@@ -75,7 +75,7 @@
3182 sender(sender),
3183 wrapped(wrapped) {}
3184
3185- bool dispatch(mir::protobuf::wire::Invocation const& invocation)
3186+ bool dispatch(mfd::Invocation const& invocation)
3187 {
3188 if ("function" == invocation.method_name())
3189 {
3190
3191=== modified file 'tests/acceptance-tests/test_surfaces_with_output_id.cpp'
3192--- tests/acceptance-tests/test_surfaces_with_output_id.cpp 2014-01-13 06:12:33 +0000
3193+++ tests/acceptance-tests/test_surfaces_with_output_id.cpp 2014-02-10 09:00:06 +0000
3194@@ -66,9 +66,11 @@
3195 f(*db);
3196 }
3197
3198- std::shared_ptr<mg::DisplayConfiguration> configuration() override
3199+ std::unique_ptr<mg::DisplayConfiguration> configuration() const override
3200 {
3201- return std::make_shared<mtd::StubDisplayConfig>(rects);
3202+ return std::unique_ptr<mg::DisplayConfiguration>(
3203+ new mtd::StubDisplayConfig(rects)
3204+ );
3205 }
3206
3207 private:
3208
3209=== modified file 'tests/draw/android_graphics.cpp'
3210--- tests/draw/android_graphics.cpp 2014-01-13 06:12:33 +0000
3211+++ tests/draw/android_graphics.cpp 2014-02-10 09:00:06 +0000
3212@@ -48,28 +48,6 @@
3213 gralloc_module_t *grmod;
3214 native_handle_t const* handle;
3215 };
3216-
3217-static const char* proc_dir = "/proc";
3218-static const char* surface_flinger_executable_name = "surfaceflinger";
3219-int surface_flinger_filter(const struct dirent* d)
3220-{
3221- if (fnmatch("[1-9]*", d->d_name, 0))
3222- return 0;
3223-
3224- char path[256];
3225- snprintf(path, sizeof(path), "%s/%s/cmdline", proc_dir, d->d_name);
3226-
3227- std::ifstream in(path);
3228- std::string line;
3229-
3230- while(std::getline(in, line))
3231- {
3232- if (line.find(surface_flinger_executable_name) != std::string::npos)
3233- return 1;
3234- }
3235-
3236- return 0;
3237-}
3238 }
3239
3240 mtd::TestGrallocMapper::TestGrallocMapper()
3241
3242=== modified file 'tests/integration-tests/client/CMakeLists.txt'
3243--- tests/integration-tests/client/CMakeLists.txt 2013-10-15 08:53:10 +0000
3244+++ tests/integration-tests/client/CMakeLists.txt 2014-02-10 09:00:06 +0000
3245@@ -4,9 +4,14 @@
3246 APPEND INTEGRATION_TESTS_SRCS
3247 ${CMAKE_CURRENT_SOURCE_DIR}/test_client_render.cpp
3248 )
3249+endif()
3250+
3251+list(
3252+ APPEND INTEGRATION_TESTS_SRCS
3253+ ${CMAKE_CURRENT_SOURCE_DIR}/test_screencast.cpp
3254+)
3255
3256 set(
3257 INTEGRATION_TESTS_SRCS
3258 ${INTEGRATION_TESTS_SRCS}
3259 PARENT_SCOPE)
3260-endif()
3261
3262=== added file 'tests/integration-tests/client/test_screencast.cpp'
3263--- tests/integration-tests/client/test_screencast.cpp 1970-01-01 00:00:00 +0000
3264+++ tests/integration-tests/client/test_screencast.cpp 2014-02-10 09:00:06 +0000
3265@@ -0,0 +1,191 @@
3266+/*
3267+ * Copyright © 2014 Canonical Ltd.
3268+ *
3269+ * This program is free software: you can redistribute it and/or modify
3270+ * it under the terms of the GNU General Public License version 3 as
3271+ * published by the Free Software Foundation.
3272+ *
3273+ * This program is distributed in the hope that it will be useful,
3274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3276+ * GNU General Public License for more details.
3277+ *
3278+ * You should have received a copy of the GNU General Public License
3279+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3280+ *
3281+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
3282+ */
3283+
3284+#include "mir_protobuf.pb.h"
3285+#include "src/client/default_connection_configuration.h"
3286+
3287+#include "mir/frontend/connector.h"
3288+#include "mir_test/test_protobuf_server.h"
3289+#include "mir_test/stub_server_tool.h"
3290+#include "mir_test/pipe.h"
3291+
3292+#include <gtest/gtest.h>
3293+
3294+#include <thread>
3295+#include <mutex>
3296+#include <condition_variable>
3297+#include <boost/throw_exception.hpp>
3298+
3299+namespace mcl = mir::client;
3300+namespace mt = mir::test;
3301+
3302+namespace
3303+{
3304+
3305+class WaitObject
3306+{
3307+public:
3308+ void notify_ready()
3309+ {
3310+ std::unique_lock<std::mutex> lock{mutex};
3311+ ready = true;
3312+ cv.notify_all();
3313+ }
3314+
3315+ void wait_until_ready()
3316+ {
3317+ std::unique_lock<std::mutex> lock{mutex};
3318+ if (!cv.wait_for(lock, std::chrono::seconds{10}, [this] { return ready; }))
3319+ {
3320+ BOOST_THROW_EXCEPTION(std::runtime_error("WaitObject timed out"));
3321+ }
3322+ }
3323+
3324+private:
3325+ std::mutex mutex;
3326+ std::condition_variable cv;
3327+ bool ready = false;
3328+};
3329+
3330+struct StubScreencastServerTool : mt::StubServerTool
3331+{
3332+ void create_screencast(
3333+ google::protobuf::RpcController*,
3334+ const mir::protobuf::ScreencastParameters*,
3335+ mir::protobuf::Screencast* response,
3336+ google::protobuf::Closure* done) override
3337+ {
3338+ response->mutable_buffer()->add_fd(pipe.read_fd());
3339+ done->Run();
3340+ }
3341+
3342+ void screencast_buffer(
3343+ ::google::protobuf::RpcController*,
3344+ ::mir::protobuf::ScreencastId const*,
3345+ ::mir::protobuf::Buffer* response,
3346+ ::google::protobuf::Closure* done) override
3347+ {
3348+ response->add_fd(pipe.read_fd());
3349+ done->Run();
3350+ }
3351+
3352+ mt::Pipe pipe;
3353+};
3354+
3355+struct MirScreencastTest : public testing::Test
3356+{
3357+ MirScreencastTest()
3358+ : server_tool{std::make_shared<StubScreencastServerTool>()}
3359+ {
3360+ std::remove(test_socket);
3361+ test_server =
3362+ std::make_shared<mt::TestProtobufServer>(test_socket, server_tool);
3363+ test_server->comm->start();
3364+
3365+ rpc_channel =
3366+ mcl::DefaultConnectionConfiguration{test_socket}.the_rpc_channel();
3367+ protobuf_server =
3368+ std::make_shared<mir::protobuf::DisplayServer::Stub>(rpc_channel.get());
3369+ }
3370+
3371+ char const* const test_socket = "./test_socket_screencast";
3372+ std::shared_ptr<StubScreencastServerTool> const server_tool;
3373+ std::shared_ptr<mt::TestProtobufServer> test_server;
3374+ std::shared_ptr<google::protobuf::RpcChannel> rpc_channel;
3375+ std::shared_ptr<mir::protobuf::DisplayServer> protobuf_server;
3376+};
3377+
3378+}
3379+
3380+TEST_F(MirScreencastTest, gets_buffer_fd_when_creating_screencast)
3381+{
3382+ std::vector<char> const cookie{'2','3','l','$'};
3383+
3384+ ASSERT_EQ(static_cast<ssize_t>(cookie.size()),
3385+ write(server_tool->pipe.write_fd(), cookie.data(), cookie.size()));
3386+
3387+ mir::protobuf::ScreencastParameters protobuf_parameters;
3388+ protobuf_parameters.set_output_id(0);
3389+ protobuf_parameters.set_width(0);
3390+ protobuf_parameters.set_height(0);
3391+ mir::protobuf::Screencast protobuf_screencast;
3392+
3393+ WaitObject wait_rpc;
3394+
3395+ protobuf_server->create_screencast(
3396+ nullptr,
3397+ &protobuf_parameters,
3398+ &protobuf_screencast,
3399+ google::protobuf::NewCallback(&wait_rpc, &WaitObject::notify_ready));
3400+
3401+ wait_rpc.wait_until_ready();
3402+
3403+ ASSERT_EQ(1, protobuf_screencast.buffer().fd_size());
3404+ auto const read_fd = protobuf_screencast.buffer().fd(0);
3405+
3406+ // The received FD should be different from the original pipe fd,
3407+ // since we are sending it over our IPC mechanism, which for
3408+ // the purposes of this test, lives in the same process.
3409+ // TODO: Don't depend on IPC implementation details
3410+ EXPECT_NE(read_fd, server_tool->pipe.read_fd());
3411+
3412+ std::vector<char> received(cookie.size(), '\0');
3413+ EXPECT_EQ(static_cast<ssize_t>(cookie.size()),
3414+ read(read_fd, received.data(), received.size()));
3415+ EXPECT_EQ(cookie, received);
3416+
3417+ close(read_fd);
3418+}
3419+
3420+TEST_F(MirScreencastTest, gets_buffer_fd_when_getting_screencast_buffer)
3421+{
3422+ std::vector<char> const cookie{'X','%','q','S'};
3423+
3424+ ASSERT_EQ(static_cast<ssize_t>(cookie.size()),
3425+ write(server_tool->pipe.write_fd(), cookie.data(), cookie.size()));
3426+
3427+ mir::protobuf::ScreencastId protobuf_screencast_id;
3428+ protobuf_screencast_id.set_value(0);
3429+ mir::protobuf::Buffer protobuf_buffer;
3430+
3431+ WaitObject wait_rpc;
3432+
3433+ protobuf_server->screencast_buffer(
3434+ nullptr,
3435+ &protobuf_screencast_id,
3436+ &protobuf_buffer,
3437+ google::protobuf::NewCallback(&wait_rpc, &WaitObject::notify_ready));
3438+
3439+ wait_rpc.wait_until_ready();
3440+
3441+ ASSERT_EQ(1, protobuf_buffer.fd_size());
3442+ auto const read_fd = protobuf_buffer.fd(0);
3443+
3444+ // The received FD should be different from the original pipe fd,
3445+ // since we are sending it over our IPC mechanism, which, for
3446+ // the purposes of this test, lives in the same process.
3447+ // TODO: Don't depend on IPC implementation details
3448+ EXPECT_NE(read_fd, server_tool->pipe.read_fd());
3449+
3450+ std::vector<char> received(cookie.size(), '\0');
3451+ EXPECT_EQ(static_cast<ssize_t>(cookie.size()),
3452+ read(read_fd, received.data(), received.size()));
3453+ EXPECT_EQ(cookie, received);
3454+
3455+ close(read_fd);
3456+}
3457
3458=== modified file 'tests/integration-tests/compositor/test_buffer_stream.cpp'
3459--- tests/integration-tests/compositor/test_buffer_stream.cpp 2014-01-13 06:12:33 +0000
3460+++ tests/integration-tests/compositor/test_buffer_stream.cpp 2014-02-10 09:00:06 +0000
3461@@ -26,6 +26,7 @@
3462
3463 #include <gmock/gmock.h>
3464
3465+#include <condition_variable>
3466 #include <thread>
3467 #include <chrono>
3468 #include <atomic>
3469@@ -38,6 +39,31 @@
3470
3471 namespace
3472 {
3473+struct BufferStreamSurfaces : mc::BufferStreamSurfaces
3474+{
3475+ using mc::BufferStreamSurfaces::BufferStreamSurfaces;
3476+
3477+ // Convenient function to allow tests to be written in linear style
3478+ void swap_client_buffers_blocking(mg::Buffer*& buffer)
3479+ {
3480+ std::mutex mutex;
3481+ std::condition_variable cv;
3482+ bool done = false;
3483+
3484+ swap_client_buffers(buffer,
3485+ [&](mg::Buffer* new_buffer)
3486+ {
3487+ std::unique_lock<decltype(mutex)> lock(mutex);
3488+ buffer = new_buffer;
3489+ done = true;
3490+ cv.notify_one();
3491+ });
3492+
3493+ std::unique_lock<decltype(mutex)> lock(mutex);
3494+
3495+ cv.wait(lock, [&]{ return done; });
3496+ }
3497+};
3498
3499 struct BufferStreamTest : public ::testing::Test
3500 {
3501@@ -60,7 +86,7 @@
3502 }
3503
3504 const int nbuffers;
3505- mc::BufferStreamSurfaces buffer_stream;
3506+ BufferStreamSurfaces buffer_stream;
3507 };
3508
3509 }
3510@@ -68,9 +94,9 @@
3511 TEST_F(BufferStreamTest, gives_same_back_buffer_until_more_available)
3512 {
3513 mg::Buffer* client1{nullptr};
3514- buffer_stream.swap_client_buffers(client1);
3515+ buffer_stream.swap_client_buffers_blocking(client1);
3516 auto client1_id = client1->id();
3517- buffer_stream.swap_client_buffers(client1);
3518+ buffer_stream.swap_client_buffers_blocking(client1);
3519
3520 auto comp1 = buffer_stream.lock_compositor_buffer(1);
3521 auto comp2 = buffer_stream.lock_compositor_buffer(1);
3522@@ -80,7 +106,7 @@
3523
3524 comp1.reset();
3525
3526- buffer_stream.swap_client_buffers(client1);
3527+ buffer_stream.swap_client_buffers_blocking(client1);
3528 auto comp3 = buffer_stream.lock_compositor_buffer(2);
3529
3530 EXPECT_NE(client1_id, comp3->id());
3531@@ -97,7 +123,7 @@
3532 {
3533 mg::Buffer* client_buffer{nullptr};
3534 for (int i = 0; i != nbuffers; i++)
3535- buffer_stream.swap_client_buffers(client_buffer);
3536+ buffer_stream.swap_client_buffers_blocking(client_buffer);
3537
3538 auto first_monitor = buffer_stream.lock_compositor_buffer(1);
3539 auto first_compositor_id = first_monitor->id();
3540@@ -113,14 +139,14 @@
3541 TEST_F(BufferStreamTest, gives_different_back_buffer_asap)
3542 {
3543 mg::Buffer* client_buffer{nullptr};
3544- buffer_stream.swap_client_buffers(client_buffer);
3545+ buffer_stream.swap_client_buffers_blocking(client_buffer);
3546
3547 if (nbuffers > 1)
3548 {
3549- buffer_stream.swap_client_buffers(client_buffer);
3550+ buffer_stream.swap_client_buffers_blocking(client_buffer);
3551 auto comp1 = buffer_stream.lock_compositor_buffer(1);
3552
3553- buffer_stream.swap_client_buffers(client_buffer);
3554+ buffer_stream.swap_client_buffers_blocking(client_buffer);
3555 auto comp2 = buffer_stream.lock_compositor_buffer(2);
3556
3557 EXPECT_NE(comp1->id(), comp2->id());
3558@@ -135,7 +161,7 @@
3559 auto old_size = buffer_stream.stream_size();
3560
3561 mg::Buffer* client{nullptr};
3562- buffer_stream.swap_client_buffers(client);
3563+ buffer_stream.swap_client_buffers_blocking(client);
3564 EXPECT_EQ(old_size, client->size());
3565
3566 geom::Size const new_size
3567@@ -146,13 +172,13 @@
3568 buffer_stream.resize(new_size);
3569 EXPECT_EQ(new_size, buffer_stream.stream_size());
3570
3571- buffer_stream.swap_client_buffers(client);
3572+ buffer_stream.swap_client_buffers_blocking(client);
3573 EXPECT_EQ(new_size, client->size());
3574
3575 buffer_stream.resize(old_size);
3576 EXPECT_EQ(old_size, buffer_stream.stream_size());
3577
3578- buffer_stream.swap_client_buffers(client);
3579+ buffer_stream.swap_client_buffers_blocking(client);
3580 EXPECT_EQ(old_size, client->size());
3581 }
3582
3583@@ -161,7 +187,7 @@
3584 auto old_size = buffer_stream.stream_size();
3585
3586 mg::Buffer* client{nullptr};
3587- buffer_stream.swap_client_buffers(client);
3588+ buffer_stream.swap_client_buffers_blocking(client);
3589
3590 geom::Size const new_size
3591 {
3592@@ -171,8 +197,8 @@
3593 buffer_stream.resize(new_size);
3594 EXPECT_EQ(new_size, buffer_stream.stream_size());
3595
3596- buffer_stream.swap_client_buffers(client);
3597- buffer_stream.swap_client_buffers(client);
3598+ buffer_stream.swap_client_buffers_blocking(client);
3599+ buffer_stream.swap_client_buffers_blocking(client);
3600
3601 auto comp1 = buffer_stream.lock_compositor_buffer(1);
3602 EXPECT_EQ(old_size, comp1->size());
3603@@ -182,7 +208,7 @@
3604 EXPECT_EQ(new_size, comp2->size());
3605 comp2.reset();
3606
3607- buffer_stream.swap_client_buffers(client);
3608+ buffer_stream.swap_client_buffers_blocking(client);
3609
3610 auto comp3 = buffer_stream.lock_compositor_buffer(3);
3611 EXPECT_EQ(new_size, comp3->size());
3612@@ -192,13 +218,13 @@
3613 EXPECT_EQ(old_size, buffer_stream.stream_size());
3614
3615 // No client frames "drawn" since resize(old_size), so compositor gets new_size
3616- buffer_stream.swap_client_buffers(client);
3617+ buffer_stream.swap_client_buffers_blocking(client);
3618 auto comp4 = buffer_stream.lock_compositor_buffer(4);
3619 EXPECT_EQ(new_size, comp4->size());
3620 comp4.reset();
3621
3622 // Generate a new frame, which should be back to old_size now
3623- buffer_stream.swap_client_buffers(client);
3624+ buffer_stream.swap_client_buffers_blocking(client);
3625 auto comp5 = buffer_stream.lock_compositor_buffer(5);
3626 EXPECT_EQ(old_size, comp5->size());
3627 comp5.reset();
3628@@ -207,8 +233,8 @@
3629 TEST_F(BufferStreamTest, can_get_partly_released_back_buffer)
3630 {
3631 mg::Buffer* client{nullptr};
3632- buffer_stream.swap_client_buffers(client);
3633- buffer_stream.swap_client_buffers(client);
3634+ buffer_stream.swap_client_buffers_blocking(client);
3635+ buffer_stream.swap_client_buffers_blocking(client);
3636
3637 auto comp1 = buffer_stream.lock_compositor_buffer(123);
3638 auto comp2 = buffer_stream.lock_compositor_buffer(123);
3639@@ -225,12 +251,12 @@
3640 namespace
3641 {
3642
3643-void client_loop(int nframes, mc::BufferStream& stream)
3644+void client_loop(int nframes, BufferStreamSurfaces& stream)
3645 {
3646 mg::Buffer* out_buffer{nullptr};
3647 for (int f = 0; f < nframes; f++)
3648 {
3649- stream.swap_client_buffers(out_buffer);
3650+ stream.swap_client_buffers_blocking(out_buffer);
3651 ASSERT_NE(nullptr, out_buffer);
3652 std::this_thread::yield();
3653 }
3654
3655=== modified file 'tests/integration-tests/compositor/test_swapping_swappers.cpp'
3656--- tests/integration-tests/compositor/test_swapping_swappers.cpp 2014-01-13 06:12:33 +0000
3657+++ tests/integration-tests/compositor/test_swapping_swappers.cpp 2014-02-10 09:00:06 +0000
3658@@ -51,6 +51,31 @@
3659 std::shared_ptr<mc::SwitchingBundle> switching_bundle;
3660 std::atomic<bool> client_thread_done;
3661 };
3662+
3663+auto client_acquire_blocking(std::shared_ptr<mc::SwitchingBundle> const& switching_bundle)
3664+-> mg::Buffer*
3665+{
3666+ std::mutex mutex;
3667+ std::condition_variable cv;
3668+ bool done = false;
3669+
3670+ mg::Buffer* result;
3671+ switching_bundle->client_acquire(
3672+ [&](mg::Buffer* new_buffer)
3673+ {
3674+ std::unique_lock<decltype(mutex)> lock(mutex);
3675+
3676+ result = new_buffer;
3677+ done = true;
3678+ cv.notify_one();
3679+ });
3680+
3681+ std::unique_lock<decltype(mutex)> lock(mutex);
3682+
3683+ cv.wait(lock, [&]{ return done; });
3684+
3685+ return result;
3686+}
3687 }
3688
3689 TEST_F(SwapperSwappingStress, swapper)
3690@@ -62,7 +87,7 @@
3691 {
3692 for(auto i=0u; i < 400; i++)
3693 {
3694- auto b = switching_bundle->client_acquire();
3695+ auto b = client_acquire_blocking(switching_bundle);
3696 std::this_thread::yield();
3697 switching_bundle->client_release(b);
3698 }
3699@@ -107,7 +132,7 @@
3700 {
3701 for(auto i=0u; i < 400; i++)
3702 {
3703- auto b = switching_bundle->client_acquire();
3704+ auto b = client_acquire_blocking(switching_bundle);
3705 std::this_thread::yield();
3706 switching_bundle->client_release(b);
3707 }
3708
3709=== modified file 'tests/integration-tests/graphics/android/test_buffer_integration.cpp'
3710--- tests/integration-tests/graphics/android/test_buffer_integration.cpp 2014-01-13 06:12:33 +0000
3711+++ tests/integration-tests/graphics/android/test_buffer_integration.cpp 2014-02-10 09:00:06 +0000
3712@@ -55,6 +55,30 @@
3713 mtd::TestGrallocMapper sw_renderer;
3714 };
3715
3716+auto client_acquire_blocking(mc::SwitchingBundle& switching_bundle)
3717+-> mg::Buffer*
3718+{
3719+ std::mutex mutex;
3720+ std::condition_variable cv;
3721+ bool done = false;
3722+
3723+ mg::Buffer* result;
3724+ switching_bundle.client_acquire(
3725+ [&](mg::Buffer* new_buffer)
3726+ {
3727+ std::unique_lock<decltype(mutex)> lock(mutex);
3728+
3729+ result = new_buffer;
3730+ done = true;
3731+ cv.notify_one();
3732+ });
3733+
3734+ std::unique_lock<decltype(mutex)> lock(mutex);
3735+
3736+ cv.wait(lock, [&]{ return done; });
3737+
3738+ return result;
3739+}
3740 }
3741
3742 TEST_F(AndroidBufferIntegration, allocator_can_create_sw_buffer)
3743@@ -92,7 +116,7 @@
3744
3745 mc::SwitchingBundle swapper(2, allocator, buffer_properties);
3746
3747- auto returned_buffer = swapper.client_acquire();
3748+ auto returned_buffer = client_acquire_blocking(swapper);
3749
3750 EXPECT_NE(nullptr, returned_buffer);
3751 }
3752
3753=== modified file 'tests/integration-tests/graphics/android/test_display_integration.cpp'
3754--- tests/integration-tests/graphics/android/test_display_integration.cpp 2014-01-21 06:27:40 +0000
3755+++ tests/integration-tests/graphics/android/test_display_integration.cpp 2014-02-10 09:00:06 +0000
3756@@ -38,7 +38,7 @@
3757
3758 namespace
3759 {
3760-class AndroidGPUDisplay : public ::testing::Test
3761+class AndroidDisplay : public ::testing::Test
3762 {
3763 protected:
3764 static void SetUpTestCase()
3765@@ -65,42 +65,17 @@
3766 static void (*original_sigterm_handler)(int);
3767 };
3768
3769-void (*AndroidGPUDisplay::original_sigterm_handler)(int);
3770-std::shared_ptr<mga::ResourceFactory> AndroidGPUDisplay::display_resource_factory;
3771-}
3772-
3773-// disabled to unblock CI - see lp:1239955
3774-TEST_F(AndroidGPUDisplay, DISABLED_gpu_display_ok_with_gles)
3775-{
3776- auto should_use_fb_fallback = true;
3777- auto buffer_initializer = std::make_shared<mg::NullBufferInitializer>();
3778- auto fb_allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>(buffer_initializer);
3779- auto mock_display_report = std::make_shared<testing::NiceMock<mtd::MockDisplayReport>>();
3780- auto display_buffer_factory = std::make_shared<mga::OutputBuilder>(
3781- fb_allocator, display_resource_factory, mock_display_report, should_use_fb_fallback);
3782-
3783- mga::AndroidDisplay display(display_buffer_factory, mock_display_report);
3784- display.for_each_display_buffer([this](mg::DisplayBuffer& buffer)
3785- {
3786- buffer.make_current();
3787- gl_animation.init_gl();
3788-
3789- gl_animation.render_gl();
3790- buffer.post_update();
3791-
3792- gl_animation.render_gl();
3793- buffer.post_update();
3794- });
3795-}
3796-
3797-TEST_F(AndroidGPUDisplay, hwc_display_ok_with_gles)
3798-{
3799- auto should_use_fb_fallback = false;
3800- auto mock_display_report = std::make_shared<testing::NiceMock<mtd::MockDisplayReport>>();
3801- auto buffer_initializer = std::make_shared<mg::NullBufferInitializer>();
3802- auto fb_allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>(buffer_initializer);
3803- auto display_buffer_factory = std::make_shared<mga::OutputBuilder>(
3804- fb_allocator, display_resource_factory, mock_display_report, should_use_fb_fallback);
3805+void (*AndroidDisplay::original_sigterm_handler)(int);
3806+std::shared_ptr<mga::ResourceFactory> AndroidDisplay::display_resource_factory;
3807+}
3808+
3809+TEST_F(AndroidDisplay, display_can_post)
3810+{
3811+ auto mock_display_report = std::make_shared<testing::NiceMock<mtd::MockDisplayReport>>();
3812+ auto buffer_initializer = std::make_shared<mg::NullBufferInitializer>();
3813+ auto fb_allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>(buffer_initializer);
3814+ auto display_buffer_factory = std::make_shared<mga::OutputBuilder>(
3815+ fb_allocator, display_resource_factory, mock_display_report);
3816
3817 mga::AndroidDisplay display(display_buffer_factory, mock_display_report);
3818 display.for_each_display_buffer([this](mg::DisplayBuffer& buffer)
3819
3820=== modified file 'tests/integration-tests/graphics/android/test_internal_client.cpp'
3821--- tests/integration-tests/graphics/android/test_internal_client.cpp 2014-01-13 06:12:33 +0000
3822+++ tests/integration-tests/graphics/android/test_internal_client.cpp 2014-02-10 09:00:06 +0000
3823@@ -98,8 +98,9 @@
3824 auto ss = std::make_shared<ms::SurfaceStack>(surface_allocator, stub_input_registrar, scene_report);
3825 auto surface_controller = std::make_shared<ms::SurfaceController>(ss);
3826 auto surface_source = std::make_shared<ms::SurfaceSource>(surface_controller, std::make_shared<mtd::NullSurfaceConfigurator>());
3827- auto mir_surface = as_internal_surface(
3828- surface_source->create_surface(nullptr, params, id, std::shared_ptr<mf::EventSink>()));
3829+ auto surface = surface_source->create_surface(nullptr, params, id, std::shared_ptr<mf::EventSink>());
3830+ surface->allow_framedropping(true);
3831+ auto mir_surface = as_internal_surface(surface);
3832
3833 auto options = std::shared_ptr<mo::ProgramOption>();
3834 auto report = std::shared_ptr<mg::NullDisplayReport>();
3835
3836=== modified file 'tests/integration-tests/test_display_server_main_loop_events.cpp'
3837--- tests/integration-tests/test_display_server_main_loop_events.cpp 2014-01-13 06:12:33 +0000
3838+++ tests/integration-tests/test_display_server_main_loop_events.cpp 2014-02-10 09:00:06 +0000
3839@@ -94,9 +94,11 @@
3840 display->for_each_display_buffer(f);
3841 }
3842
3843- std::shared_ptr<mg::DisplayConfiguration> configuration() override
3844+ std::unique_ptr<mg::DisplayConfiguration> configuration() const override
3845 {
3846- return display->configuration();
3847+ return std::unique_ptr<mg::DisplayConfiguration>(
3848+ new mtd::NullDisplayConfiguration
3849+ );
3850 }
3851
3852 MOCK_METHOD1(configure, void(mg::DisplayConfiguration const&));
3853
3854=== modified file 'tests/integration-tests/test_session.cpp'
3855--- tests/integration-tests/test_session.cpp 2014-01-14 07:02:27 +0000
3856+++ tests/integration-tests/test_session.cpp 2014-02-10 09:00:06 +0000
3857@@ -1,5 +1,5 @@
3858 /*
3859- * Copyright © 2013 Canonical Ltd.
3860+ * Copyright © 2013-2014 Canonical Ltd.
3861 *
3862 * This program is free software: you can redistribute it and/or modify
3863 * it under the terms of the GNU General Public License version 3 as
3864@@ -170,6 +170,7 @@
3865
3866 ms::ApplicationSession session{
3867 conf.the_shell_surface_factory(),
3868+ __LINE__,
3869 "stress",
3870 conf.the_snapshot_strategy(),
3871 std::make_shared<msh::NullSessionListener>(),
3872@@ -189,7 +190,7 @@
3873 for (int i = 0; i < 500; ++i)
3874 {
3875 auto surface = session.default_surface();
3876- surface->swap_buffers(buffer);
3877+ surface->swap_buffers_blocking(buffer);
3878 std::this_thread::sleep_for(std::chrono::microseconds{50});
3879 }
3880 }};
3881
3882=== modified file 'tests/integration-tests/test_session_manager.cpp'
3883--- tests/integration-tests/test_session_manager.cpp 2014-01-13 06:12:33 +0000
3884+++ tests/integration-tests/test_session_manager.cpp 2014-02-10 09:00:06 +0000
3885@@ -76,9 +76,9 @@
3886
3887 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
3888
3889- auto session1 = session_manager.open_session("Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
3890- auto session2 = session_manager.open_session("Microsoft Access", std::make_shared<mtd::NullEventSink>());
3891- auto session3 = session_manager.open_session("WordPerfect", std::make_shared<mtd::NullEventSink>());
3892+ auto session1 = session_manager.open_session(__LINE__, "Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
3893+ auto session2 = session_manager.open_session(__LINE__, "Microsoft Access", std::make_shared<mtd::NullEventSink>());
3894+ auto session3 = session_manager.open_session(__LINE__, "WordPerfect", std::make_shared<mtd::NullEventSink>());
3895
3896 Mock::VerifyAndClearExpectations(&focus_setter);
3897
3898@@ -105,9 +105,9 @@
3899
3900 EXPECT_CALL(focus_setter, set_focus_to(_)).Times(3);
3901
3902- auto session1 = session_manager.open_session("Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
3903- auto session2 = session_manager.open_session("Microsoft Access", std::make_shared<mtd::NullEventSink>());
3904- auto session3 = session_manager.open_session("WordPerfect", std::make_shared<mtd::NullEventSink>());
3905+ auto session1 = session_manager.open_session(__LINE__, "Visual Basic Studio", std::make_shared<mtd::NullEventSink>());
3906+ auto session2 = session_manager.open_session(__LINE__, "Microsoft Access", std::make_shared<mtd::NullEventSink>());
3907+ auto session3 = session_manager.open_session(__LINE__, "WordPerfect", std::make_shared<mtd::NullEventSink>());
3908
3909 Mock::VerifyAndClearExpectations(&focus_setter);
3910
3911
3912=== modified file 'tests/integration-tests/test_swapinterval.cpp'
3913--- tests/integration-tests/test_swapinterval.cpp 2014-01-13 06:12:33 +0000
3914+++ tests/integration-tests/test_swapinterval.cpp 2014-02-10 09:00:06 +0000
3915@@ -56,14 +56,22 @@
3916 {
3917 }
3918
3919- void swap_client_buffers(mg::Buffer*& buffer) { buffer = &stub_buffer; }
3920- std::shared_ptr<mg::Buffer> lock_compositor_buffer(unsigned long) { return std::make_shared<mtd::StubBuffer>(); }
3921- std::shared_ptr<mg::Buffer> lock_snapshot_buffer() { return std::make_shared<mtd::StubBuffer>(); }
3922- MirPixelFormat get_stream_pixel_format() { return mir_pixel_format_abgr_8888; }
3923- geom::Size stream_size() { return geom::Size{}; }
3924+ void swap_client_buffers(mg::Buffer*, std::function<void(mg::Buffer* new_buffer)> complete) override
3925+ { complete(&stub_buffer); }
3926+
3927+ std::shared_ptr<mg::Buffer> lock_compositor_buffer(unsigned long) override
3928+ { return std::make_shared<mtd::StubBuffer>(); }
3929+
3930+ std::shared_ptr<mg::Buffer> lock_snapshot_buffer() override
3931+ { return std::make_shared<mtd::StubBuffer>(); }
3932+
3933+ MirPixelFormat get_stream_pixel_format() override
3934+ { return mir_pixel_format_abgr_8888; }
3935+
3936+ geom::Size stream_size() override { return geom::Size{}; }
3937 void resize(geom::Size const&) override {}
3938- void force_requests_to_complete() {}
3939- void allow_framedropping(bool)
3940+ void force_requests_to_complete() override {}
3941+ void allow_framedropping(bool) override
3942 {
3943 while (write(render_operations_fd, "a", 1) != 1) continue;
3944 }
3945
3946=== modified file 'tests/mir_test_framework/stubbed_server_configuration.cpp'
3947--- tests/mir_test_framework/stubbed_server_configuration.cpp 2014-01-29 12:51:30 +0000
3948+++ tests/mir_test_framework/stubbed_server_configuration.cpp 2014-02-10 09:00:06 +0000
3949@@ -120,7 +120,7 @@
3950 class StubDisplayConfiguration : public mtd::NullDisplayConfiguration
3951 {
3952 public:
3953- StubDisplayConfiguration(geom::Rectangle& rect)
3954+ StubDisplayConfiguration(geom::Rectangle const& rect)
3955 : modes{mg::DisplayConfigurationMode{rect.size, 1.0f}}
3956 {
3957 }
3958@@ -156,9 +156,11 @@
3959 f(display_buffer);
3960 }
3961
3962- std::shared_ptr<mg::DisplayConfiguration> configuration() override
3963+ std::unique_ptr<mg::DisplayConfiguration> configuration() const override
3964 {
3965- return std::make_shared<StubDisplayConfiguration>(rect);
3966+ return std::unique_ptr<mg::DisplayConfiguration>(
3967+ new StubDisplayConfiguration(rect)
3968+ );
3969 }
3970
3971 private:
3972
3973=== modified file 'tests/unit-tests/client/test_mir_screencast.cpp'
3974--- tests/unit-tests/client/test_mir_screencast.cpp 2014-01-24 18:11:19 +0000
3975+++ tests/unit-tests/client/test_mir_screencast.cpp 2014-02-10 09:00:06 +0000
3976@@ -67,12 +67,17 @@
3977 void create_screencast(
3978 google::protobuf::RpcController* /*controller*/,
3979 mp::ScreencastParameters const* /*request*/,
3980- mp::Screencast* /*response*/,
3981+ mp::Screencast* response,
3982 google::protobuf::Closure* done) override
3983 {
3984 if (server_thread.joinable())
3985 server_thread.join();
3986- server_thread = std::thread{[done, this] { done->Run(); }};
3987+ server_thread = std::thread{
3988+ [response, done, this]
3989+ {
3990+ response->clear_error();
3991+ done->Run();
3992+ }};
3993 }
3994
3995 void release_screencast(
3996@@ -151,6 +156,7 @@
3997
3998 ACTION_P(SetCreateScreencastId, screencast_id)
3999 {
4000+ arg2->clear_error();
4001 arg2->mutable_screencast_id()->set_value(screencast_id);
4002 }
4003
4004@@ -166,6 +172,7 @@
4005
4006 ACTION_P(SetCreateBufferFromPackage, package)
4007 {
4008+ arg2->clear_error();
4009 auto buffer = arg2->mutable_buffer();
4010 for (int i = 0; i != package.data_items; ++i)
4011 {
4012@@ -180,6 +187,11 @@
4013 buffer->set_stride(package.stride);
4014 }
4015
4016+ACTION(SetCreateError)
4017+{
4018+ arg2->set_error("Test error");
4019+}
4020+
4021 ACTION(RunClosure)
4022 {
4023 arg3->Run();
4024@@ -521,3 +533,41 @@
4025
4026 EXPECT_EQ(StubEGLNativeWindowFactory::egl_native_window, egl_native_window);
4027 }
4028+
4029+TEST_F(MirScreencastTest, is_invalid_if_server_create_screencast_fails)
4030+{
4031+ using namespace testing;
4032+
4033+ EXPECT_CALL(mock_server, create_screencast(_,_,_,_))
4034+ .WillOnce(DoAll(SetCreateError(), RunClosure()));
4035+
4036+ MirScreencast screencast{
4037+ default_mir_output, mock_server,
4038+ stub_egl_native_window_factory,
4039+ stub_client_buffer_factory,
4040+ null_callback_func, nullptr};
4041+
4042+ screencast.creation_wait_handle()->wait_for_all();
4043+
4044+ EXPECT_FALSE(screencast.valid());
4045+}
4046+
4047+TEST_F(MirScreencastTest, calls_callback_on_creation_failure)
4048+{
4049+ using namespace testing;
4050+
4051+ MockCallback mock_cb;
4052+ EXPECT_CALL(mock_server, create_screencast(_,_,_,_))
4053+ .WillOnce(DoAll(SetCreateError(), RunClosure()));
4054+ EXPECT_CALL(mock_cb, call(_,&mock_cb));
4055+
4056+ MirScreencast screencast{
4057+ default_mir_output, mock_server,
4058+ stub_egl_native_window_factory,
4059+ stub_client_buffer_factory,
4060+ mock_callback_func, &mock_cb};
4061+
4062+ screencast.creation_wait_handle()->wait_for_all();
4063+
4064+ EXPECT_FALSE(screencast.valid());
4065+}
4066
4067=== modified file 'tests/unit-tests/compositor/test_buffer_stream.cpp'
4068--- tests/unit-tests/compositor/test_buffer_stream.cpp 2014-01-13 06:12:33 +0000
4069+++ tests/unit-tests/compositor/test_buffer_stream.cpp 2014-02-10 09:00:06 +0000
4070@@ -25,6 +25,8 @@
4071 #include <gmock/gmock.h>
4072 #include <gtest/gtest.h>
4073
4074+#include <condition_variable>
4075+
4076 namespace mc = mir::compositor;
4077 namespace mg = mir::graphics;
4078 namespace geom = mir::geometry;
4079@@ -122,22 +124,50 @@
4080
4081 TEST_F(BufferStreamTest, get_buffer_for_client_releases_resources)
4082 {
4083- using namespace testing;
4084- mc::BufferStreamSurfaces buffer_stream(mock_bundle);
4085+ std::mutex mutex;
4086+ std::condition_variable cv;
4087 mg::Buffer* buffer{nullptr};
4088+ bool done = false;
4089+
4090+ auto const callback =
4091+ [&](mg::Buffer* new_buffer)
4092+ {
4093+ std::unique_lock<decltype(mutex)> lock(mutex);
4094+ buffer = new_buffer;
4095+ done = true;
4096+ cv.notify_one();
4097+ };
4098+
4099+ using namespace testing;
4100+ mc::BufferStreamSurfaces buffer_stream(mock_bundle);
4101
4102 InSequence seq;
4103- EXPECT_CALL(*mock_bundle, client_acquire())
4104+ EXPECT_CALL(*mock_bundle, client_acquire(_))
4105 .Times(1)
4106- .WillOnce(Return(mock_buffer.get()));
4107+ .WillOnce(InvokeArgument<0>(mock_buffer.get()));
4108 EXPECT_CALL(*mock_bundle, client_release(_))
4109 .Times(1);
4110- EXPECT_CALL(*mock_bundle, client_acquire())
4111+ EXPECT_CALL(*mock_bundle, client_acquire(_))
4112 .Times(1)
4113- .WillOnce(Return(mock_buffer.get()));
4114-
4115- buffer_stream.swap_client_buffers(buffer);
4116- buffer_stream.swap_client_buffers(buffer);
4117+ .WillOnce(InvokeArgument<0>(mock_buffer.get()));
4118+
4119+ buffer_stream.swap_client_buffers(buffer, callback);
4120+
4121+ {
4122+ std::unique_lock<decltype(mutex)> lock(mutex);
4123+
4124+ cv.wait(lock, [&]{ return done; });
4125+ }
4126+
4127+ done = false;
4128+
4129+ buffer_stream.swap_client_buffers(buffer, callback);
4130+
4131+ {
4132+ std::unique_lock<decltype(mutex)> lock(mutex);
4133+
4134+ cv.wait(lock, [&]{ return done; });
4135+ }
4136 }
4137
4138 TEST_F(BufferStreamTest, allow_framedropping_device)
4139
4140=== modified file 'tests/unit-tests/compositor/test_switching_bundle.cpp'
4141--- tests/unit-tests/compositor/test_switching_bundle.cpp 2014-01-22 14:15:29 +0000
4142+++ tests/unit-tests/compositor/test_switching_bundle.cpp 2014-02-10 09:00:06 +0000
4143@@ -34,6 +34,8 @@
4144
4145 using namespace testing;
4146
4147+namespace
4148+{
4149 struct SwitchingBundleTest : public ::testing::Test
4150 {
4151 void SetUp()
4152@@ -52,6 +54,32 @@
4153 mg::BufferProperties basic_properties;
4154 };
4155
4156+auto client_acquire_blocking(mc::SwitchingBundle& switching_bundle)
4157+-> mg::Buffer*
4158+{
4159+ std::mutex mutex;
4160+ std::condition_variable cv;
4161+ bool done = false;
4162+
4163+ mg::Buffer* result;
4164+ switching_bundle.client_acquire(
4165+ [&](mg::Buffer* new_buffer)
4166+ {
4167+ std::unique_lock<decltype(mutex)> lock(mutex);
4168+
4169+ result = new_buffer;
4170+ done = true;
4171+ cv.notify_one();
4172+ });
4173+
4174+ std::unique_lock<decltype(mutex)> lock(mutex);
4175+
4176+ cv.wait(lock, [&]{ return done; });
4177+
4178+ return result;
4179+}
4180+}
4181+
4182 TEST_F(SwitchingBundleTest, sync_swapper_by_default)
4183 {
4184 mg::BufferProperties properties{geom::Size{7, 8},
4185@@ -100,7 +128,7 @@
4186 {
4187 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
4188
4189- auto buffer = bundle.client_acquire();
4190+ auto buffer = client_acquire_blocking(bundle);
4191 bundle.client_release(buffer);
4192 }
4193 }
4194@@ -132,7 +160,7 @@
4195
4196 for (int i = 0; i < 20; i++)
4197 {
4198- auto client1 = bundle.client_acquire();
4199+ auto client1 = client_acquire_blocking(bundle);
4200 mg::BufferID expect_id = client1->id(), composited_id;
4201 bundle.client_release(client1);
4202
4203@@ -173,7 +201,7 @@
4204 {
4205 for (int j = 0; j < 100; j++)
4206 {
4207- auto client = bundle.client_acquire();
4208+ auto client = client_acquire_blocking(bundle);
4209 last_client_id = client->id();
4210 bundle.client_release(client);
4211 }
4212@@ -197,11 +225,11 @@
4213 { // Regression test for LP: #1210042
4214 mc::SwitchingBundle bundle(3, allocator, basic_properties);
4215
4216- auto client1 = bundle.client_acquire();
4217+ auto client1 = client_acquire_blocking(bundle);
4218 auto client1_id = client1->id();
4219 bundle.client_release(client1);
4220
4221- auto client2 = bundle.client_acquire();
4222+ auto client2 = client_acquire_blocking(bundle);
4223 bundle.client_release(client2);
4224
4225 auto compositor = bundle.compositor_acquire(1);
4226@@ -217,8 +245,8 @@
4227 {
4228 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
4229
4230- auto client1 = bundle.client_acquire();
4231- auto client2 = bundle.client_acquire();
4232+ auto client1 = client_acquire_blocking(bundle);
4233+ auto client2 = client_acquire_blocking(bundle);
4234 EXPECT_THROW(
4235 bundle.client_release(client2),
4236 std::logic_error
4237@@ -241,7 +269,7 @@
4238 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
4239 unsigned long frameno = 0;
4240
4241- auto client = bundle.client_acquire();
4242+ auto client = client_acquire_blocking(bundle);
4243 auto client_id = client->id();
4244 bundle.client_release(client);
4245
4246@@ -291,7 +319,7 @@
4247 {
4248 if (i % 10 == 0)
4249 {
4250- auto client = bundle.client_acquire();
4251+ auto client = client_acquire_blocking(bundle);
4252 client_id = client->id();
4253 bundle.client_release(client);
4254 }
4255@@ -317,7 +345,7 @@
4256 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
4257 unsigned long frameno = 0;
4258
4259- auto client = bundle.client_acquire();
4260+ auto client = client_acquire_blocking(bundle);
4261 bundle.client_release(client);
4262
4263 auto compositor1 = bundle.compositor_acquire(++frameno);
4264@@ -342,11 +370,11 @@
4265 mg::Buffer* client_buffer = nullptr;
4266 std::shared_ptr<mg::Buffer> compositor_buffer = nullptr;
4267
4268- client_buffer = bundle.client_acquire();
4269+ client_buffer = client_acquire_blocking(bundle);
4270 mg::BufferID first_ready_buffer_id = client_buffer->id();
4271 bundle.client_release(client_buffer);
4272
4273- client_buffer = bundle.client_acquire();
4274+ client_buffer = client_acquire_blocking(bundle);
4275
4276 // in the original bug, compositor would be given the wrong buffer here
4277 compositor_buffer = bundle.compositor_acquire(0 /*frameno*/);
4278@@ -371,11 +399,11 @@
4279
4280 std::shared_ptr<mg::Buffer> compositor[2];
4281
4282- bundle.client_release(bundle.client_acquire());
4283+ bundle.client_release(client_acquire_blocking(bundle));
4284 compositor[0] = bundle.compositor_acquire(frameno);
4285
4286 frameno++;
4287- bundle.client_release(bundle.client_acquire());
4288+ bundle.client_release(client_acquire_blocking(bundle));
4289 compositor[1] = bundle.compositor_acquire(frameno);
4290
4291 for (int i = 0; i < 20; i++)
4292@@ -386,7 +414,7 @@
4293 // One of the compositors (the oldest one) gets a new buffer...
4294 int oldest = i & 1;
4295 bundle.compositor_release(compositor[oldest]);
4296- bundle.client_release(bundle.client_acquire());
4297+ bundle.client_release(client_acquire_blocking(bundle));
4298 frameno++;
4299 compositor[oldest] = bundle.compositor_acquire(frameno);
4300 }
4301@@ -445,7 +473,7 @@
4302 std::logic_error
4303 );
4304
4305- auto client = bundle.client_acquire();
4306+ auto client = client_acquire_blocking(bundle);
4307 auto snapshot = bundle.snapshot_acquire();
4308
4309 EXPECT_EQ(compositor->id(), snapshot->id());
4310@@ -488,7 +516,7 @@
4311 {
4312 for (int i = 0; i < nframes; i++)
4313 {
4314- bundle.client_release(bundle.client_acquire());
4315+ bundle.client_release(client_acquire_blocking(bundle));
4316 std::this_thread::yield();
4317 }
4318 }
4319@@ -499,12 +527,12 @@
4320 {
4321 bundle.allow_framedropping(false);
4322 for (int j = 0; j < 5; j++)
4323- bundle.client_release(bundle.client_acquire());
4324+ bundle.client_release(client_acquire_blocking(bundle));
4325 std::this_thread::yield();
4326
4327 bundle.allow_framedropping(true);
4328 for (int j = 0; j < 5; j++)
4329- bundle.client_release(bundle.client_acquire());
4330+ bundle.client_release(client_acquire_blocking(bundle));
4331 std::this_thread::yield();
4332 }
4333 }
4334@@ -602,11 +630,11 @@
4335
4336 std::shared_ptr<mg::Buffer> compositor[2];
4337
4338- bundle.client_release(bundle.client_acquire());
4339+ bundle.client_release(client_acquire_blocking(bundle));
4340 compositor[0] = bundle.compositor_acquire(frameno);
4341
4342 frameno++;
4343- bundle.client_release(bundle.client_acquire());
4344+ bundle.client_release(client_acquire_blocking(bundle));
4345 compositor[1] = bundle.compositor_acquire(frameno);
4346
4347 for (int i = 0; i < 20; i++)
4348@@ -614,7 +642,7 @@
4349 // Two compositors acquired, and they're always different...
4350 ASSERT_NE(compositor[0]->id(), compositor[1]->id());
4351
4352- auto client = bundle.client_acquire();
4353+ auto client = client_acquire_blocking(bundle);
4354 ASSERT_NE(compositor[0]->id(), client->id());
4355 ASSERT_NE(compositor[1]->id(), client->id());
4356 bundle.client_release(client);
4357@@ -648,7 +676,7 @@
4358
4359 for (int b = 0; b < nbuffers; b++)
4360 {
4361- buf[b] = bundle.client_acquire();
4362+ buf[b] = client_acquire_blocking(bundle);
4363 expect[b] = buf[b]->id();
4364
4365 for (int p = 0; p < b; p++)
4366@@ -660,7 +688,7 @@
4367
4368 for (int frame = 0; frame < nframes; frame++)
4369 {
4370- auto client = bundle.client_acquire();
4371+ auto client = client_acquire_blocking(bundle);
4372 ASSERT_EQ(expect[frame % nbuffers], client->id());
4373 bundle.client_release(client);
4374 }
4375@@ -739,11 +767,11 @@
4376 }
4377 });
4378
4379- bundle.client_release(bundle.client_acquire());
4380+ bundle.client_release(client_acquire_blocking(bundle));
4381
4382 while (!done.load())
4383 {
4384- bundle.client_release(bundle.client_acquire());
4385+ bundle.client_release(client_acquire_blocking(bundle));
4386 client_frames++;
4387 }
4388
4389@@ -789,13 +817,13 @@
4390 }
4391 });
4392
4393- bundle.client_release(bundle.client_acquire());
4394+ bundle.client_release(client_acquire_blocking(bundle));
4395
4396 while (!done.load())
4397 {
4398 sync.lock();
4399 sync.unlock();
4400- auto buf = bundle.client_acquire();
4401+ auto buf = client_acquire_blocking(bundle);
4402 std::this_thread::sleep_for(frame_time);
4403 bundle.client_release(buf);
4404 client_frames++;
4405@@ -825,7 +853,7 @@
4406 for (int subframe = 0; subframe < 3; ++subframe)
4407 {
4408 bundle.resize(expect_size);
4409- auto client = bundle.client_acquire();
4410+ auto client = client_acquire_blocking(bundle);
4411 ASSERT_EQ(expect_size, client->size());
4412 bundle.client_release(client);
4413
4414@@ -861,7 +889,7 @@
4415 height += dy;
4416
4417 bundle.resize(new_size);
4418- auto client = bundle.client_acquire();
4419+ auto client = client_acquire_blocking(bundle);
4420 history[produce] = client->id();
4421 ASSERT_EQ(new_size, client->size());
4422 bundle.client_release(client);
4423
4424=== modified file 'tests/unit-tests/compositor/test_temporary_buffers.cpp'
4425--- tests/unit-tests/compositor/test_temporary_buffers.cpp 2014-01-13 06:12:33 +0000
4426+++ tests/unit-tests/compositor/test_temporary_buffers.cpp 2014-02-10 09:00:06 +0000
4427@@ -52,8 +52,8 @@
4428 {
4429 using namespace testing;
4430
4431- ON_CALL(*mock_bundle, client_acquire())
4432- .WillByDefault(Return(mock_buffer.get()));
4433+ ON_CALL(*mock_bundle, client_acquire(_))
4434+ .WillByDefault(InvokeArgument<0>(mock_buffer.get()));
4435 ON_CALL(*mock_bundle, compositor_acquire(_))
4436 .WillByDefault(Return(mock_buffer));
4437 }
4438
4439=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
4440--- tests/unit-tests/frontend/test_session_mediator.cpp 2014-01-13 06:55:38 +0000
4441+++ tests/unit-tests/frontend/test_session_mediator.cpp 2014-02-10 09:00:06 +0000
4442@@ -1,5 +1,5 @@
4443 /*
4444- * Copyright © 2012 Canonical Ltd.
4445+ * Copyright © 2012-2014 Canonical Ltd.
4446 *
4447 * This program is free software: you can redistribute it and/or modify
4448 * it under the terms of the GNU General Public License version 3 as
4449@@ -39,6 +39,7 @@
4450 #include "mir_test_doubles/stub_surface_builder.h"
4451 #include "mir_test_doubles/stub_display_configuration.h"
4452 #include "mir_test_doubles/stub_buffer_allocator.h"
4453+#include "mir_test_doubles/null_screencast.h"
4454 #include "mir_test/display_config_matchers.h"
4455 #include "mir_test/fake_shared.h"
4456 #include "mir/frontend/event_sink.h"
4457@@ -103,7 +104,8 @@
4458
4459 EXPECT_CALL(*mock_surface, size()).Times(AnyNumber()).WillRepeatedly(Return(geom::Size()));
4460 EXPECT_CALL(*mock_surface, pixel_format()).Times(AnyNumber()).WillRepeatedly(Return(MirPixelFormat()));
4461- EXPECT_CALL(*mock_surface, swap_buffers(_)).Times(AnyNumber()).WillRepeatedly(SetArg<0>(mock_buffer.get()));
4462+ EXPECT_CALL(*mock_surface, swap_buffers(_, _)).Times(AnyNumber())
4463+ .WillRepeatedly(InvokeArgument<1>(mock_buffer.get()));
4464
4465 EXPECT_CALL(*mock_surface, supports_input()).Times(AnyNumber()).WillRepeatedly(Return(true));
4466 EXPECT_CALL(*mock_surface, client_input_fd()).Times(AnyNumber()).WillRepeatedly(Return(testing_client_input_fd));
4467@@ -123,7 +125,8 @@
4468
4469 EXPECT_CALL(*mock_surfaces[id], size()).Times(AnyNumber()).WillRepeatedly(Return(geom::Size()));
4470 EXPECT_CALL(*mock_surfaces[id], pixel_format()).Times(AnyNumber()).WillRepeatedly(Return(MirPixelFormat()));
4471- EXPECT_CALL(*mock_surfaces[id], swap_buffers(_)).Times(AnyNumber()).WillRepeatedly(SetArg<0>(mock_buffer.get()));
4472+ EXPECT_CALL(*mock_surfaces[id], swap_buffers(_, _)).Times(AnyNumber())
4473+ .WillRepeatedly(InvokeArgument<1>(mock_buffer.get()));
4474
4475 EXPECT_CALL(*mock_surfaces[id], supports_input()).Times(AnyNumber()).WillRepeatedly(Return(true));
4476 EXPECT_CALL(*mock_surfaces[id], client_input_fd()).Times(AnyNumber()).WillRepeatedly(Return(testing_client_input_fd));
4477@@ -183,6 +186,16 @@
4478 MOCK_CONST_METHOD0(egl_native_display, EGLNativeDisplayType());
4479 };
4480
4481+struct StubScreencast : mtd::NullScreencast
4482+{
4483+ std::shared_ptr<mg::Buffer> capture(mf::ScreencastSessionId)
4484+ {
4485+ return mt::fake_shared(stub_buffer);
4486+ }
4487+
4488+ mtd::StubBuffer stub_buffer;
4489+};
4490+
4491 struct SessionMediatorTest : public ::testing::Test
4492 {
4493 SessionMediatorTest()
4494@@ -192,16 +205,17 @@
4495 surface_pixel_formats{mir_pixel_format_argb_8888, mir_pixel_format_xrgb_8888},
4496 report{std::make_shared<mf::NullSessionMediatorReport>()},
4497 resource_cache{std::make_shared<mf::ResourceCache>()},
4498- mediator{shell, graphics_platform, graphics_changer,
4499+ stub_screencast{std::make_shared<StubScreencast>()},
4500+ mediator{__LINE__, shell, graphics_platform, graphics_changer,
4501 surface_pixel_formats, report,
4502 std::make_shared<mtd::NullEventSink>(),
4503- resource_cache},
4504+ resource_cache, stub_screencast},
4505 stubbed_session{std::make_shared<StubbedSession>()},
4506 null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)}
4507 {
4508 using namespace ::testing;
4509
4510- ON_CALL(*shell, open_session(_, _)).WillByDefault(Return(stubbed_session));
4511+ ON_CALL(*shell, open_session(_, _, _)).WillByDefault(Return(stubbed_session));
4512 ON_CALL(*shell, create_surface_for(_, _))
4513 .WillByDefault(WithArg<1>(Invoke(stubbed_session.get(), &StubbedSession::create_surface)));
4514 }
4515@@ -212,6 +226,7 @@
4516 std::vector<MirPixelFormat> const surface_pixel_formats;
4517 std::shared_ptr<mf::SessionMediatorReport> const report;
4518 std::shared_ptr<mf::ResourceCache> const resource_cache;
4519+ std::shared_ptr<StubScreencast> const stub_screencast;
4520 mf::SessionMediator mediator;
4521 std::shared_ptr<StubbedSession> const stubbed_session;
4522
4523@@ -355,10 +370,10 @@
4524 .Times(1)
4525 .WillOnce(Return(mt::fake_shared(config)));
4526 mf::SessionMediator mediator(
4527- shell, graphics_platform, mock_display,
4528+ __LINE__, shell, graphics_platform, mock_display,
4529 surface_pixel_formats, report,
4530 std::make_shared<mtd::NullEventSink>(),
4531- resource_cache);
4532+ resource_cache, std::make_shared<mtd::NullScreencast>());
4533
4534 mp::ConnectParameters connect_parameters;
4535 mp::Connection connection;
4536@@ -461,6 +476,8 @@
4537 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
4538
4539 {
4540+ // AFAICS these values are stubs to set up the test condition,
4541+ // the exact calls here are not a *requirement* on SessionMediator
4542 EXPECT_CALL(*stubbed_session->mock_buffer, id())
4543 .WillOnce(Return(mg::BufferID{4}))
4544 .WillOnce(Return(mg::BufferID{4}))
4545@@ -519,8 +536,8 @@
4546 * the pre-created stubbed_session->mock_surface. Further create_surface()
4547 * invocations create new surfaces in stubbed_session->mock_surfaces[].
4548 */
4549- EXPECT_CALL(*stubbed_session->mock_surface, swap_buffers(_))
4550- .WillOnce(SetArg<0>(&buffer));
4551+ EXPECT_CALL(*stubbed_session->mock_surface, swap_buffers(_, _))
4552+ .WillOnce(InvokeArgument<1>(&buffer));
4553
4554 mediator.create_surface(nullptr, &surface_request, &surface_response, null_callback.get());
4555 mp::SurfaceId our_surface{surface_response.id()};
4556@@ -528,7 +545,7 @@
4557 Mock::VerifyAndClearExpectations(stubbed_session->mock_surface.get());
4558
4559 /* Creating a new surface should not affect our surfaces' buffers */
4560- EXPECT_CALL(*stubbed_session->mock_surface, swap_buffers(_)).Times(0);
4561+ EXPECT_CALL(*stubbed_session->mock_surface, swap_buffers(_, _)).Times(0);
4562 mediator.create_surface(nullptr, &surface_request, &surface_response, null_callback.get());
4563
4564 mp::SurfaceId new_surface{surface_response.id()};
4565@@ -540,7 +557,7 @@
4566 Mock::VerifyAndClearExpectations(stubbed_session->mock_surface.get());
4567
4568 /* Getting the next buffer of our surface should post the original */
4569- EXPECT_CALL(*stubbed_session->mock_surface, swap_buffers(Eq(&buffer))).Times(1);
4570+ EXPECT_CALL(*stubbed_session->mock_surface, swap_buffers(Eq(&buffer), _)).Times(1);
4571
4572 mediator.next_buffer(nullptr, &our_surface, &buffer_response, null_callback.get());
4573 mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get());
4574@@ -585,9 +602,10 @@
4575 .WillOnce(Return(mt::fake_shared(stub_display_config)));
4576
4577 mf::SessionMediator session_mediator{
4578- shell, graphics_platform, mock_display_selector,
4579+ __LINE__, shell, graphics_platform, mock_display_selector,
4580 surface_pixel_formats, report,
4581- std::make_shared<mtd::NullEventSink>(), resource_cache};
4582+ std::make_shared<mtd::NullEventSink>(), resource_cache,
4583+ std::make_shared<mtd::NullScreencast>()};
4584
4585 session_mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
4586
4587@@ -620,3 +638,38 @@
4588
4589 session_mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get());
4590 }
4591+
4592+TEST_F(SessionMediatorTest, fully_packs_buffer_for_create_screencast)
4593+{
4594+ using namespace testing;
4595+
4596+ mp::ScreencastParameters screencast_parameters;
4597+ mp::Screencast screencast;
4598+ auto const& stub_buffer = stub_screencast->stub_buffer;
4599+
4600+ EXPECT_CALL(*graphics_platform, fill_ipc_package(_, &stub_buffer));
4601+
4602+ mediator.create_screencast(nullptr, &screencast_parameters,
4603+ &screencast, null_callback.get());
4604+
4605+ EXPECT_EQ(stub_buffer.id().as_uint32_t(),
4606+ screencast.buffer().buffer_id());
4607+}
4608+
4609+TEST_F(SessionMediatorTest, partially_packs_buffer_for_screencast_buffer)
4610+{
4611+ using namespace testing;
4612+
4613+ mp::ScreencastId screencast_id;
4614+ mp::Buffer protobuf_buffer;
4615+ auto const& stub_buffer = stub_screencast->stub_buffer;
4616+
4617+ EXPECT_CALL(*graphics_platform, fill_ipc_package(_, &stub_buffer))
4618+ .Times(0);
4619+
4620+ mediator.screencast_buffer(nullptr, &screencast_id,
4621+ &protobuf_buffer, null_callback.get());
4622+
4623+ EXPECT_EQ(stub_buffer.id().as_uint32_t(),
4624+ protobuf_buffer.buffer_id());
4625+}
4626
4627=== modified file 'tests/unit-tests/frontend/test_session_mediator_android.cpp'
4628--- tests/unit-tests/frontend/test_session_mediator_android.cpp 2014-01-13 06:12:33 +0000
4629+++ tests/unit-tests/frontend/test_session_mediator_android.cpp 2014-02-10 09:00:06 +0000
4630@@ -32,6 +32,7 @@
4631 #include "mir_test_doubles/null_platform.h"
4632 #include "mir_test_doubles/null_event_sink.h"
4633 #include "mir_test_doubles/stub_buffer_allocator.h"
4634+#include "mir_test_doubles/null_screencast.h"
4635
4636 #include <gtest/gtest.h>
4637
4638@@ -56,10 +57,10 @@
4639 surface_pixel_formats{mir_pixel_format_argb_8888, mir_pixel_format_xrgb_8888},
4640 report{std::make_shared<mf::NullSessionMediatorReport>()},
4641 resource_cache{std::make_shared<mf::ResourceCache>()},
4642- mediator{shell, graphics_platform, display_changer,
4643+ mediator{__LINE__, shell, graphics_platform, display_changer,
4644 surface_pixel_formats, report,
4645 std::make_shared<mtd::NullEventSink>(),
4646- resource_cache},
4647+ resource_cache, std::make_shared<mtd::NullScreencast>()},
4648 null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)}
4649 {
4650 }
4651
4652=== modified file 'tests/unit-tests/frontend/test_session_mediator_mesa.cpp'
4653--- tests/unit-tests/frontend/test_session_mediator_mesa.cpp 2014-01-13 06:12:33 +0000
4654+++ tests/unit-tests/frontend/test_session_mediator_mesa.cpp 2014-02-10 09:00:06 +0000
4655@@ -1,5 +1,5 @@
4656 /*
4657- * Copyright © 2012 Canonical Ltd.
4658+ * Copyright © 2012-2014 Canonical Ltd.
4659 *
4660 * This program is free software: you can redistribute it and/or modify
4661 * it under the terms of the GNU General Public License version 3 as
4662@@ -34,6 +34,7 @@
4663 #include "mir_test_doubles/null_platform.h"
4664 #include "mir_test_doubles/mock_session.h"
4665 #include "mir_test_doubles/stub_shell.h"
4666+#include "mir_test_doubles/null_screencast.h"
4667
4668 #include <gtest/gtest.h>
4669 #include <gmock/gmock.h>
4670@@ -69,10 +70,10 @@
4671 surface_pixel_formats{mir_pixel_format_argb_8888, mir_pixel_format_xrgb_8888},
4672 report{std::make_shared<mf::NullSessionMediatorReport>()},
4673 resource_cache{std::make_shared<mf::ResourceCache>()},
4674- mediator{shell, mock_platform, display_changer,
4675+ mediator{__LINE__, shell, mock_platform, display_changer,
4676 surface_pixel_formats, report,
4677 std::make_shared<mtd::NullEventSink>(),
4678- resource_cache},
4679+ resource_cache, std::make_shared<mtd::NullScreencast>()},
4680 null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)}
4681 {
4682 }
4683
4684=== modified file 'tests/unit-tests/frontend/test_socket_session.cpp'
4685--- tests/unit-tests/frontend/test_socket_session.cpp 2014-01-22 15:54:11 +0000
4686+++ tests/unit-tests/frontend/test_socket_session.cpp 2014-02-10 09:00:06 +0000
4687@@ -70,7 +70,7 @@
4688
4689 struct MockProcessor : public mfd::MessageProcessor
4690 {
4691- MOCK_METHOD1(dispatch, bool(mir::protobuf::wire::Invocation const& invocation));
4692+ MOCK_METHOD1(dispatch, bool(mfd::Invocation const& invocation));
4693 };
4694 }
4695 struct SocketSessionTest : public ::testing::Test
4696
4697=== modified file 'tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp'
4698--- tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp 2014-01-13 06:12:33 +0000
4699+++ tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp 2014-02-10 09:00:06 +0000
4700@@ -236,7 +236,7 @@
4701
4702 TEST_F(AdaptorICSTest, handle_has_version)
4703 {
4704- int version = 96; /* version value shared by JB and ICS */
4705+ int version = sizeof(ANativeWindowBuffer); /* version value shared by JB and ICS */
4706 auto native_handle = alloc_adaptor->alloc_buffer(size, pf, usage);
4707 auto anwb = native_handle->anwb();
4708 EXPECT_EQ(version, anwb->common.version);
4709
4710=== modified file 'tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp'
4711--- tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp 2014-01-13 06:12:33 +0000
4712+++ tests/unit-tests/graphics/android/test_buffer_tex_bind.cpp 2014-02-10 09:00:06 +0000
4713@@ -101,7 +101,8 @@
4714 TEST_F(AndroidBufferBinding, buffer_makes_new_image_with_new_display)
4715 {
4716 using namespace testing;
4717- EGLDisplay second_fake_display = (EGLDisplay) ((int)mock_egl.fake_egl_display +1);
4718+ EGLDisplay second_fake_display =
4719+ reinterpret_cast<EGLDisplay>(&second_fake_display);
4720
4721 /* return 1st fake display */
4722 EXPECT_CALL(mock_egl, eglCreateImageKHR(_,_,_,_,_))
4723@@ -121,7 +122,8 @@
4724 TEST_F(AndroidBufferBinding, buffer_frees_images_it_makes)
4725 {
4726 using namespace testing;
4727- EGLDisplay second_fake_display = (EGLDisplay) ((int)mock_egl.fake_egl_display +1);
4728+ EGLDisplay second_fake_display =
4729+ reinterpret_cast<EGLDisplay>(&second_fake_display);
4730
4731 EXPECT_CALL(mock_egl, eglDestroyImageKHR(_,_))
4732 .Times(Exactly(2));
4733@@ -141,9 +143,12 @@
4734 using namespace testing;
4735
4736 EGLDisplay first_fake_display = mock_egl.fake_egl_display;
4737- EGLImageKHR first_fake_egl_image = (EGLImageKHR) 0x84210;
4738- EGLDisplay second_fake_display = (EGLDisplay) ((int)mock_egl.fake_egl_display +1);
4739- EGLImageKHR second_fake_egl_image = (EGLImageKHR) 0x84211;
4740+ EGLImageKHR first_fake_egl_image =
4741+ reinterpret_cast<EGLImageKHR>(&first_fake_egl_image);
4742+ EGLDisplay second_fake_display =
4743+ reinterpret_cast<EGLDisplay>(&second_fake_display);
4744+ EGLImageKHR second_fake_egl_image =
4745+ reinterpret_cast<EGLImageKHR>(&second_fake_egl_image);
4746
4747 /* actual expectations */
4748 EXPECT_CALL(mock_egl, eglDestroyImageKHR(first_fake_display, first_fake_egl_image))
4749@@ -321,8 +326,10 @@
4750 TEST_F(AndroidBufferBinding, buffer_binding_uses_right_image_after_display_swap)
4751 {
4752 using namespace testing;
4753- EGLDisplay second_fake_display = (EGLDisplay) ((int)mock_egl.fake_egl_display +1);
4754- EGLImageKHR second_fake_egl_image = (EGLImageKHR) 0x84211;
4755+ EGLDisplay second_fake_display =
4756+ reinterpret_cast<EGLDisplay>(&second_fake_display);
4757+ EGLImageKHR second_fake_egl_image =
4758+ reinterpret_cast<EGLImageKHR>(&second_fake_egl_image);
4759
4760 EXPECT_CALL(mock_egl, glEGLImageTargetTexture2DOES(_, _))
4761 .Times(Exactly(1));
4762
4763=== modified file 'tests/unit-tests/graphics/android/test_hwc_common_device.cpp'
4764--- tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-01-21 18:09:35 +0000
4765+++ tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-02-10 09:00:06 +0000
4766@@ -16,6 +16,7 @@
4767 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
4768 */
4769
4770+#include "mir/graphics/android/sync_fence.h"
4771 #include "src/platform/graphics/android/hwc_fb_device.h"
4772 #include "src/platform/graphics/android/hwc_device.h"
4773 #include "src/platform/graphics/android/hwc_layerlist.h"
4774@@ -58,7 +59,8 @@
4775 std::shared_ptr<framebuffer_device_t> const&,
4776 std::shared_ptr<mga::HWCVsyncCoordinator> const& coordinator)
4777 {
4778- return std::make_shared<mga::HwcDevice>(hwc_device, coordinator);
4779+ auto file_ops = std::make_shared<mga::RealSyncFileOps>();
4780+ return std::make_shared<mga::HwcDevice>(hwc_device, coordinator, file_ops);
4781 }
4782
4783 template<typename T>
4784
4785=== modified file 'tests/unit-tests/graphics/android/test_hwc_device.cpp'
4786--- tests/unit-tests/graphics/android/test_hwc_device.cpp 2014-01-23 17:26:51 +0000
4787+++ tests/unit-tests/graphics/android/test_hwc_device.cpp 2014-02-10 09:00:06 +0000
4788@@ -16,6 +16,7 @@
4789 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
4790 */
4791
4792+#include "mir/graphics/android/sync_fence.h"
4793 #include "src/platform/graphics/android/framebuffer_bundle.h"
4794 #include "src/platform/graphics/android/hwc_device.h"
4795 #include "src/platform/graphics/android/hwc_layerlist.h"
4796@@ -35,6 +36,16 @@
4797 namespace mtd=mir::test::doubles;
4798 namespace geom=mir::geometry;
4799
4800+namespace
4801+{
4802+struct MockFileOps : public mga::SyncFileOps
4803+{
4804+ MOCK_METHOD3(ioctl, int(int,int,void*));
4805+ MOCK_METHOD1(dup, int(int));
4806+ MOCK_METHOD1(close, int(int));
4807+};
4808+}
4809+
4810 class HwcDevice : public ::testing::Test
4811 {
4812 protected:
4813@@ -48,10 +59,13 @@
4814 mock_buffer = std::make_shared<testing::NiceMock<mtd::MockBuffer>>();
4815 mock_device = std::make_shared<testing::NiceMock<mtd::MockHWCComposerDevice1>>();
4816 mock_vsync = std::make_shared<testing::NiceMock<mtd::MockVsyncCoordinator>>();
4817+ mock_file_ops = std::make_shared<MockFileOps>();
4818
4819 ON_CALL(*mock_buffer, native_buffer_handle())
4820 .WillByDefault(Return(mock_native_buffer));
4821 }
4822+
4823+ std::shared_ptr<MockFileOps> mock_file_ops;
4824 std::shared_ptr<mtd::MockVsyncCoordinator> mock_vsync;
4825 std::shared_ptr<mtd::MockHWCComposerDevice1> mock_device;
4826 std::shared_ptr<mtd::MockAndroidNativeBuffer> mock_native_buffer;
4827@@ -69,7 +83,7 @@
4828 EXPECT_CALL(*mock_device, set_interface(mock_device.get(),_,_))
4829 .Times(1);
4830
4831- mga::HwcDevice device(mock_device, mock_vsync);
4832+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4833 device.prepare_gl();
4834 device.post(*mock_buffer);
4835
4836@@ -90,7 +104,7 @@
4837 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))
4838 .Times(1);
4839
4840- mga::HwcDevice device(mock_device, mock_vsync);
4841+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4842 device.prepare_gl();
4843 EXPECT_EQ(2, mock_device->display0_prepare_content.numHwLayers);
4844 EXPECT_EQ(-1, mock_device->display0_prepare_content.retireFenceFd);
4845@@ -102,7 +116,7 @@
4846 EXPECT_CALL(*mock_device, prepare_interface(mock_device.get(), 1, _))
4847 .Times(1);
4848
4849- mga::HwcDevice device(mock_device, mock_vsync);
4850+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4851 std::list<std::shared_ptr<mg::Renderable>> renderlist;
4852 device.prepare_gl_and_overlays(renderlist);
4853
4854@@ -114,7 +128,7 @@
4855 {
4856 EXPECT_CALL(mock_egl, eglSwapBuffers(dpy,surf))
4857 .Times(1);
4858- mga::HwcDevice device(mock_device, mock_vsync);
4859+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4860 device.gpu_render(dpy, surf);
4861 }
4862
4863@@ -125,7 +139,7 @@
4864 .Times(1)
4865 .WillOnce(Return(EGL_FALSE));
4866
4867- mga::HwcDevice device(mock_device, mock_vsync);
4868+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4869
4870 EXPECT_THROW({
4871 device.gpu_render(dpy, surf);
4872@@ -136,15 +150,19 @@
4873 {
4874 using namespace testing;
4875 int hwc_return_fence = 94;
4876+ int hwc_retire_fence = 74;
4877 mock_device->hwc_set_return_fence(hwc_return_fence);
4878+ mock_device->hwc_set_retire_fence(hwc_retire_fence);
4879
4880- mga::HwcDevice device(mock_device, mock_vsync);
4881+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4882
4883 InSequence seq;
4884 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), 1, _))
4885 .Times(1);
4886 EXPECT_CALL(*mock_native_buffer, update_fence(hwc_return_fence))
4887 .Times(1);
4888+ EXPECT_CALL(*mock_file_ops, close(hwc_retire_fence))
4889+ .Times(1);
4890
4891 device.post(*mock_buffer);
4892
4893@@ -161,7 +179,7 @@
4894 {
4895 using namespace testing;
4896
4897- mga::HwcDevice device(mock_device, mock_vsync);
4898+ mga::HwcDevice device(mock_device, mock_vsync, mock_file_ops);
4899
4900 EXPECT_CALL(*mock_device, set_interface(mock_device.get(), _, _))
4901 .Times(1)
4902
4903=== modified file 'tests/unit-tests/graphics/android/test_output_builder.cpp'
4904--- tests/unit-tests/graphics/android/test_output_builder.cpp 2014-01-21 18:09:35 +0000
4905+++ tests/unit-tests/graphics/android/test_output_builder.cpp 2014-02-10 09:00:06 +0000
4906@@ -122,7 +122,7 @@
4907 .Times(1);
4908
4909 mga::OutputBuilder factory(
4910- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4911+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4912 factory.create_display_device();
4913 }
4914
4915@@ -143,7 +143,7 @@
4916 .Times(1);
4917
4918 mga::OutputBuilder factory(
4919- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4920+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4921 factory.create_display_device();
4922 }
4923
4924@@ -161,7 +161,7 @@
4925 .Times(1);
4926
4927 mga::OutputBuilder factory(
4928- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4929+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4930 factory.create_display_device();
4931 }
4932
4933@@ -182,7 +182,7 @@
4934 .Times(1);
4935
4936 mga::OutputBuilder factory(
4937- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4938+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4939 factory.create_display_device();
4940 }
4941
4942@@ -201,7 +201,7 @@
4943
4944 EXPECT_THROW({
4945 mga::OutputBuilder factory(
4946- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4947+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4948 }, std::runtime_error);
4949 }
4950
4951@@ -219,7 +219,7 @@
4952 .Times(1);
4953
4954 mga::OutputBuilder factory(
4955- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4956+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4957 factory.create_display_device();
4958 }
4959
4960@@ -233,6 +233,6 @@
4961 .Times(1);
4962
4963 mga::OutputBuilder factory(
4964- mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report, false);
4965+ mt::fake_shared(mock_buffer_allocator),mock_resource_factory, mock_display_report);
4966 factory.create_display_buffer(mt::fake_shared(stub_device), gl_context);
4967 }
4968
4969=== modified file 'tests/unit-tests/graphics/mesa/test_display_configuration.cpp'
4970--- tests/unit-tests/graphics/mesa/test_display_configuration.cpp 2014-01-13 06:12:33 +0000
4971+++ tests/unit-tests/graphics/mesa/test_display_configuration.cpp 2014-02-10 09:00:06 +0000
4972@@ -289,7 +289,7 @@
4973 /* Test body */
4974 auto display = create_display(create_platform());
4975
4976- auto conf = display->configuration();
4977+ std::shared_ptr<mg::DisplayConfiguration> conf = display->configuration();
4978 auto const& kms_conf = std::static_pointer_cast<mgm::KMSDisplayConfiguration>(conf);
4979
4980 size_t output_count{0};
4981@@ -332,7 +332,7 @@
4982 /* Test body */
4983 auto display = create_display(create_platform());
4984
4985- auto conf = display->configuration();
4986+ std::shared_ptr<mg::DisplayConfiguration> conf = display->configuration();
4987 auto const& kms_conf = std::static_pointer_cast<mgm::KMSDisplayConfiguration>(conf);
4988
4989 EXPECT_THROW({
4990
4991=== modified file 'tests/unit-tests/scene/test_application_session.cpp'
4992--- tests/unit-tests/scene/test_application_session.cpp 2014-01-13 06:12:33 +0000
4993+++ tests/unit-tests/scene/test_application_session.cpp 2014-02-10 09:00:06 +0000
4994@@ -1,5 +1,5 @@
4995 /*
4996- * Copyright © 2012 Canonical Ltd.
4997+ * Copyright © 2012-2014 Canonical Ltd.
4998 *
4999 * This program is free software: you can redistribute it and/or modify
5000 * it under the terms of the GNU General Public License version 3 as
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches