Mir

Merge lp:~afrantzis/mir/vt-switching-1 into lp:~mir-team/mir/trunk

Proposed by Alexandros Frantzis on 2013-04-11
Status: Merged
Approved by: Alexandros Frantzis on 2013-04-12
Approved revision: 584
Merged at revision: 585
Proposed branch: lp:~afrantzis/mir/vt-switching-1
Merge into: lp:~mir-team/mir/trunk
Diff against target: 1824 lines (+935/-65)
33 files modified
include/server/mir/graphics/display.h (+11/-0)
include/test/mir_test_doubles/mock_display.h (+5/-0)
include/test/mir_test_doubles/null_display.h (+7/-0)
include/test/mir_test_doubles/null_virtual_terminal.h (+47/-0)
src/server/display_server.cpp (+12/-0)
src/server/graphics/android/android_display.cpp (+15/-0)
src/server/graphics/android/android_display.h (+8/-0)
src/server/graphics/gbm/CMakeLists.txt (+1/-0)
src/server/graphics/gbm/gbm_display.cpp (+31/-3)
src/server/graphics/gbm/gbm_display.h (+12/-2)
src/server/graphics/gbm/gbm_display_buffer.cpp (+17/-2)
src/server/graphics/gbm/gbm_display_buffer.h (+4/-0)
src/server/graphics/gbm/gbm_display_helpers.cpp (+40/-0)
src/server/graphics/gbm/gbm_display_helpers.h (+3/-0)
src/server/graphics/gbm/gbm_platform.cpp (+9/-4)
src/server/graphics/gbm/gbm_platform.h (+7/-2)
src/server/graphics/gbm/linux_virtual_terminal.cpp (+180/-0)
src/server/graphics/gbm/linux_virtual_terminal.h (+67/-0)
src/server/graphics/gbm/virtual_terminal.h (+55/-0)
tests/behavior-tests/session_management_context.cpp (+9/-0)
tests/integration-tests/test_display_server_main_loop_events.cpp (+178/-0)
tests/integration-tests/test_surfaceloop.cpp (+7/-0)
tests/mir_test_framework/testing_server_options.cpp (+7/-0)
tests/unit-tests/compositor/test_multi_threaded_compositor.cpp (+7/-0)
tests/unit-tests/graphics/gbm/mock_drm.cpp (+10/-0)
tests/unit-tests/graphics/gbm/mock_drm.h (+3/-0)
tests/unit-tests/graphics/gbm/test_gbm_buffer.cpp (+4/-1)
tests/unit-tests/graphics/gbm/test_gbm_buffer_allocator.cpp (+3/-1)
tests/unit-tests/graphics/gbm/test_gbm_display.cpp (+117/-31)
tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp (+13/-6)
tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp (+12/-5)
tests/unit-tests/graphics/gbm/test_gbm_platform.cpp (+18/-5)
tests/unit-tests/graphics/test_graphics_platform.cpp (+16/-3)
To merge this branch: bzr merge lp:~afrantzis/mir/vt-switching-1
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration 2013-04-11 Approve on 2013-04-12
Daniel van Vugt 2013-04-11 Abstain on 2013-04-12
Robert Carr (community) 2013-04-11 Approve on 2013-04-11
Kevin DuBois (community) Approve on 2013-04-11
Robert Ancell 2013-04-11 Pending
Review via email: mp+158327@code.launchpad.net

This proposal supersedes a proposal from 2013-04-10.

Commit message

server,gbm: Support VT switching

Since VT switching is a desktop specific concept at the moment, this branch
introduces it in more generic terms, as pause/resume in the high level
interfaces. Note that the mechanisms that implement pausing/resuming are
not tied to VT switching in particular. We can reuse them to pause/resume
arbitrarily.

In order for VT switching (pause/resume) to work properly, mir needs to be
run with root privileges, since this is required for drm{Drop,Set}Master().
However, if no VT switch (pause/resume) is performed, mir can be happily
run without root priveleges (as before, assuming appropriate device
permissions).

Description of the change

server,gbm: Support VT switching

Since VT switching is a desktop specific concept, this branch introduces it in more generic terms, as pause/resume in the high level interfaces. Note that the mechanisms that implement pausing/resuming are not tied to VT switching in particular. We can reuse them to pause/resume arbitrarily.

In order for VT switching (pause/resume) to work properly, mir needs to be run with root privileges, since this is required for drm{Drop,Set}Master(). However, if no VT switch (pause/resume) is performed, mir can be happily run without root priveleges (as before, assuming appropriate device permissions).

There is a bit of code churn in this branch because of the interface changes in mg::Display and mg::Platform, that caused a barrage of amendments to related stub and mock classes.

To post a comment you must log in.
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Around + display->pause();

Do we need to pause input?

review: Needs Information
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> Around + display->pause();
>
> Do we need to pause input?

Good question, we probably do, but I am not familiar with input details and how moving to another VT affects input. I guess from the perspective of pause/resume, it makes sense to stop processing/sending input events anyway when paused.

In any case, I'd rather leave it out of this MP (and let you implement it in an upcoming MP as needed ;))

Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

The concepts of pause/resume (although not coded to do anything in android) are useful for what we'll want to do when the display is turned off on android, so I like the general idea

I kept thinking the pause/resume for the platform and the display could be consilidated, however I think its ok as it is

Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> I kept thinking the pause/resume for the platform and the display could be
> consilidated, however I think its ok as it is

This is doable, although less explicit, but on second thought I prefer it this way too.
We can also move register_pause_resume_handlers() to mg::Display too, thus leaving the mg::Platform interface unchanged.

Robert Ancell (robert-ancell) : Posted in a previous version of this proposal
review: Approve
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Text conflict in include/server/mir/graphics/platform.h
Text conflict in src/server/graphics/android/android_platform.h
Text conflict in src/server/graphics/gbm/gbm_platform.cpp
Text conflict in src/server/graphics/gbm/gbm_platform.h
Text conflict in tests/integration-tests/graphics/gbm/test_buffer_integration.cpp
Text conflict in tests/integration-tests/test_display_info.cpp
Text conflict in tests/integration-tests/test_drm_auth_magic.cpp
Text conflict in tests/integration-tests/test_surfaceloop.cpp
Text conflict in tests/mir_test_framework/testing_server_options.cpp
Text conflict in tests/unit-tests/frontend/test_session_mediator.cpp
Text conflict in tests/unit-tests/frontend/test_session_mediator_android.cpp
Text conflict in tests/unit-tests/frontend/test_session_mediator_gbm.cpp
Text conflict in tests/unit-tests/graphics/gbm/mock_drm.cpp
Text conflict in tests/unit-tests/graphics/gbm/mock_drm.h
14 conflicts encountered.

review: Needs Fixing
Alexandros Frantzis (afrantzis) wrote :

> I kept thinking the pause/resume for the platform and the display could be consilidated

Fixed.

> Text conflict in include/server/mir/graphics/platform.h
...

Fixed.

Kevin DuBois (kdub) wrote :

okay, with the consolidated pause/resume, this looks good to me

review: Approve
Robert Carr (robertcarr) wrote :

I like the changes to consolidate pause/resume on display...was going to ask about this :)

I think it lgtm to me as it stands!

I wonder if LinuxVirtualTerminal should use some interface for the ioctls so it can be unit tested for interaction.

review: Approve
Daniel van Vugt (vanvugt) wrote :

I can't test this any more. Blocked by bug 1167828 for now.

review: Abstain
Alexandros Frantzis (afrantzis) wrote :

> I like the changes to consolidate pause/resume on display...was going to ask
> about this :)
>
> I think it lgtm to me as it stands!
>
> I wonder if LinuxVirtualTerminal should use some interface for the ioctls so
> it can be unit tested for interaction.

Yes, ideally it should. I considered adding an, e.g., FileOperations dependency on LinuxVirtualTerminal, but decided against it for this MP to keep it small. In retrospect, I should have proposed this differently: use a DummyVirtualTerminal for this MP, and add the real VT implementation in a different one. Anyway, I will fix this in an upcoming MP.

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/server/mir/graphics/display.h'
2--- include/server/mir/graphics/display.h 2013-03-13 04:54:15 +0000
3+++ include/server/mir/graphics/display.h 2013-04-11 11:00:30 +0000
4@@ -26,6 +26,9 @@
5
6 namespace mir
7 {
8+
9+class MainLoop;
10+
11 namespace graphics
12 {
13
14@@ -40,6 +43,14 @@
15
16 virtual std::shared_ptr<DisplayConfiguration> configuration() = 0;
17
18+ virtual void register_pause_resume_handlers(
19+ MainLoop& main_loop,
20+ std::function<void()> const& pause_handler,
21+ std::function<void()> const& resume_handler) = 0;
22+
23+ virtual void pause() = 0;
24+ virtual void resume() = 0;
25+
26 protected:
27 Display() = default;
28 ~Display() = default;
29
30=== modified file 'include/test/mir_test_doubles/mock_display.h'
31--- include/test/mir_test_doubles/mock_display.h 2013-03-13 04:54:15 +0000
32+++ include/test/mir_test_doubles/mock_display.h 2013-04-11 11:00:30 +0000
33@@ -35,6 +35,11 @@
34 MOCK_CONST_METHOD0(view_area, geometry::Rectangle ());
35 MOCK_METHOD1(for_each_display_buffer, void (std::function<void(graphics::DisplayBuffer&)> const&));
36 MOCK_METHOD0(configuration, std::shared_ptr<graphics::DisplayConfiguration>());
37+ MOCK_METHOD3(register_pause_resume_handlers, void(MainLoop&,
38+ std::function<void()> const&,
39+ std::function<void()> const&));
40+ MOCK_METHOD0(pause, void());
41+ MOCK_METHOD0(resume, void());
42 };
43
44 }
45
46=== modified file 'include/test/mir_test_doubles/null_display.h'
47--- include/test/mir_test_doubles/null_display.h 2013-03-13 04:54:15 +0000
48+++ include/test/mir_test_doubles/null_display.h 2013-04-11 11:00:30 +0000
49@@ -42,6 +42,13 @@
50 {
51 return std::shared_ptr<graphics::DisplayConfiguration>();
52 }
53+ void register_pause_resume_handlers(MainLoop&,
54+ std::function<void()> const&,
55+ std::function<void()> const&)
56+ {
57+ }
58+ void pause() {}
59+ void resume() {}
60 };
61
62 }
63
64=== added file 'include/test/mir_test_doubles/null_virtual_terminal.h'
65--- include/test/mir_test_doubles/null_virtual_terminal.h 1970-01-01 00:00:00 +0000
66+++ include/test/mir_test_doubles/null_virtual_terminal.h 2013-04-11 11:00:30 +0000
67@@ -0,0 +1,47 @@
68+/*
69+ * Copyright © 2013 Canonical Ltd.
70+ *
71+ * This program is free software: you can redistribute it and/or modify it
72+ * under the terms of the GNU Lesser General Public License version 3,
73+ * as published by the Free Software Foundation.
74+ *
75+ * This program is distributed in the hope that it will be useful,
76+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
77+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78+ * GNU General Public License for more details.
79+ *
80+ * You should have received a copy of the GNU Lesser General Public License
81+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
82+ *
83+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
84+ */
85+
86+#ifndef MIR_TEST_DOUBLES_NULL_VIRTUAL_TERMINAL_H_
87+#define MIR_TEST_DOUBLES_NULL_VIRTUAL_TERMINAL_H_
88+
89+#include "src/server/graphics/gbm/virtual_terminal.h"
90+
91+namespace mir
92+{
93+namespace test
94+{
95+namespace doubles
96+{
97+
98+class NullVirtualTerminal : public graphics::gbm::VirtualTerminal
99+{
100+public:
101+ void set_graphics_mode() {}
102+
103+ void register_switch_handlers(MainLoop&,
104+ std::function<void()> const&,
105+ std::function<void()> const&)
106+ {
107+ }
108+};
109+
110+}
111+}
112+}
113+
114+#endif /* MIR_TEST_DOUBLES_NULL_VIRTUAL_TERMINAL_H_ */
115
116=== modified file 'src/server/display_server.cpp'
117--- src/server/display_server.cpp 2013-04-10 16:23:54 +0000
118+++ src/server/display_server.cpp 2013-04-11 11:00:30 +0000
119@@ -44,6 +44,18 @@
120 input_manager{config.the_input_manager()},
121 main_loop{config.the_main_loop()}
122 {
123+ display->register_pause_resume_handlers(
124+ *main_loop,
125+ [this]
126+ {
127+ compositor->stop();
128+ display->pause();
129+ },
130+ [this]
131+ {
132+ display->resume();
133+ compositor->start();
134+ });
135 }
136
137 std::shared_ptr<mg::Display> display;
138
139=== modified file 'src/server/graphics/android/android_display.cpp'
140--- src/server/graphics/android/android_display.cpp 2013-03-21 03:32:59 +0000
141+++ src/server/graphics/android/android_display.cpp 2013-04-11 11:00:30 +0000
142@@ -142,6 +142,21 @@
143 return std::make_shared<NullDisplayConfiguration>();
144 }
145
146+void mga::AndroidDisplay::register_pause_resume_handlers(
147+ MainLoop& /*main_loop*/,
148+ std::function<void()> const& /*pause_handler*/,
149+ std::function<void()> const& /*resume_handler*/)
150+{
151+}
152+
153+void mga::AndroidDisplay::pause()
154+{
155+}
156+
157+void mga::AndroidDisplay::resume()
158+{
159+}
160+
161 void mga::AndroidDisplay::make_current()
162 {
163 if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE)
164
165=== modified file 'src/server/graphics/android/android_display.h'
166--- src/server/graphics/android/android_display.h 2013-03-22 18:33:51 +0000
167+++ src/server/graphics/android/android_display.h 2013-04-11 11:00:30 +0000
168@@ -50,6 +50,14 @@
169
170 std::shared_ptr<DisplayConfiguration> configuration();
171
172+ void register_pause_resume_handlers(
173+ MainLoop& main_loop,
174+ std::function<void()> const& pause_handler,
175+ std::function<void()> const& resume_handler);
176+
177+ void pause();
178+ void resume();
179+
180 void make_current();
181 private:
182 std::shared_ptr<AndroidFramebufferWindowQuery> native_window;
183
184=== modified file 'src/server/graphics/gbm/CMakeLists.txt'
185--- src/server/graphics/gbm/CMakeLists.txt 2013-03-13 04:54:15 +0000
186+++ src/server/graphics/gbm/CMakeLists.txt 2013-04-11 11:00:30 +0000
187@@ -24,6 +24,7 @@
188 kms_output.cpp
189 kms_output_container.cpp
190 kms_page_flipper.cpp
191+ linux_virtual_terminal.cpp
192 )
193
194 target_link_libraries(
195
196=== modified file 'src/server/graphics/gbm/gbm_display.cpp'
197--- src/server/graphics/gbm/gbm_display.cpp 2013-03-13 04:54:15 +0000
198+++ src/server/graphics/gbm/gbm_display.cpp 2013-04-11 11:00:30 +0000
199@@ -22,6 +22,7 @@
200 #include "kms_display_configuration.h"
201 #include "kms_output.h"
202 #include "kms_page_flipper.h"
203+#include "virtual_terminal.h"
204
205 #include "mir/geometry/rectangle.h"
206
207@@ -36,6 +37,8 @@
208 output_container{platform->drm.fd,
209 std::make_shared<KMSPageFlipper>(platform->drm.fd)}
210 {
211+ platform->vt->set_graphics_mode();
212+
213 shared_egl.setup(platform->gbm);
214
215 configure(configuration());
216@@ -43,6 +46,10 @@
217 shared_egl.make_current();
218 }
219
220+mgg::GBMDisplay::~GBMDisplay()
221+{
222+}
223+
224 geom::Rectangle mgg::GBMDisplay::view_area() const
225 {
226 return display_buffers[0]->view_area();
227@@ -92,8 +99,29 @@
228 max_size.height.as_uint32_t());
229
230 /* Create a single DisplayBuffer that displays the surface on all the outputs */
231- std::unique_ptr<DisplayBuffer> db{new GBMDisplayBuffer{platform, listener, enabled_outputs,
232- std::move(surface), max_size,
233- shared_egl.context()}};
234+ std::unique_ptr<GBMDisplayBuffer> db{new GBMDisplayBuffer{platform, listener, enabled_outputs,
235+ std::move(surface), max_size,
236+ shared_egl.context()}};
237 display_buffers.push_back(std::move(db));
238 }
239+
240+void mgg::GBMDisplay::register_pause_resume_handlers(
241+ MainLoop& main_loop,
242+ std::function<void()> const& pause_handler,
243+ std::function<void()> const& resume_handler)
244+{
245+ platform->vt->register_switch_handlers(main_loop, pause_handler, resume_handler);
246+}
247+
248+void mgg::GBMDisplay::pause()
249+{
250+ platform->drm.drop_master();
251+}
252+
253+void mgg::GBMDisplay::resume()
254+{
255+ platform->drm.set_master();
256+
257+ for (auto& db_ptr : display_buffers)
258+ db_ptr->schedule_set_crtc();
259+}
260
261=== modified file 'src/server/graphics/gbm/gbm_display.h'
262--- src/server/graphics/gbm/gbm_display.h 2013-03-21 03:32:59 +0000
263+++ src/server/graphics/gbm/gbm_display.h 2013-04-11 11:00:30 +0000
264@@ -20,7 +20,6 @@
265 #define MIR_GRAPHICS_GBM_GBM_DISPLAY_H_
266
267 #include "mir/graphics/display.h"
268-#include "mir/graphics/display_buffer.h"
269 #include "kms_output_container.h"
270 #include "gbm_display_helpers.h"
271
272@@ -36,31 +35,42 @@
273 {
274
275 class DisplayReport;
276+class DisplayBuffer;
277
278 namespace gbm
279 {
280
281 class GBMPlatform;
282 class KMSOutput;
283+class GBMDisplayBuffer;
284
285 class GBMDisplay : public Display
286 {
287 public:
288 GBMDisplay(std::shared_ptr<GBMPlatform> const& platform,
289 std::shared_ptr<DisplayReport> const& listener);
290+ ~GBMDisplay();
291
292 geometry::Rectangle view_area() const;
293 void for_each_display_buffer(std::function<void(DisplayBuffer&)> const& f);
294
295 std::shared_ptr<DisplayConfiguration> configuration();
296
297+ void register_pause_resume_handlers(
298+ MainLoop& main_loop,
299+ std::function<void()> const& pause_handler,
300+ std::function<void()> const& resume_handler);
301+
302+ void pause();
303+ void resume();
304+
305 private:
306 void configure(std::shared_ptr<DisplayConfiguration> const& conf);
307
308 std::shared_ptr<GBMPlatform> const platform;
309 std::shared_ptr<DisplayReport> const listener;
310 helpers::EGLHelper shared_egl;
311- std::vector<std::unique_ptr<DisplayBuffer>> display_buffers;
312+ std::vector<std::unique_ptr<GBMDisplayBuffer>> display_buffers;
313 KMSOutputContainer output_container;
314 };
315
316
317=== modified file 'src/server/graphics/gbm/gbm_display_buffer.cpp'
318--- src/server/graphics/gbm/gbm_display_buffer.cpp 2013-03-21 03:32:59 +0000
319+++ src/server/graphics/gbm/gbm_display_buffer.cpp 2013-04-11 11:00:30 +0000
320@@ -105,7 +105,8 @@
321 drm(platform->drm),
322 outputs(outputs),
323 surface_gbm{std::move(surface_gbm_param)},
324- size(size)
325+ size(size),
326+ needs_set_crtc{false}
327 {
328 egl.setup(platform->gbm, surface_gbm.get(), shared_context);
329
330@@ -180,11 +181,20 @@
331 * If the flip fails, release the buffer object to make it available
332 * for future rendering.
333 */
334- if (!schedule_and_wait_for_page_flip(bufobj))
335+ if (!needs_set_crtc && !schedule_and_wait_for_page_flip(bufobj))
336 {
337 bufobj->release();
338 return false;
339 }
340+ else if (needs_set_crtc)
341+ {
342+ for (auto& output : outputs)
343+ {
344+ if (!output->set_crtc(bufobj->get_drm_fb_id()))
345+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to set DRM crtc"));
346+ }
347+ needs_set_crtc = false;
348+ }
349
350 /*
351 * Release the last flipped buffer object (which is not displayed anymore)
352@@ -265,3 +275,8 @@
353 BOOST_THROW_EXCEPTION(std::runtime_error("Failed to make EGL surface current"));
354 }
355 }
356+
357+void mgg::GBMDisplayBuffer::schedule_set_crtc()
358+{
359+ needs_set_crtc = true;
360+}
361
362=== modified file 'src/server/graphics/gbm/gbm_display_buffer.h'
363--- src/server/graphics/gbm/gbm_display_buffer.h 2013-03-13 04:54:15 +0000
364+++ src/server/graphics/gbm/gbm_display_buffer.h 2013-04-11 11:00:30 +0000
365@@ -24,6 +24,7 @@
366
367 #include <vector>
368 #include <memory>
369+#include <atomic>
370
371 namespace mir
372 {
373@@ -55,6 +56,8 @@
374 void clear();
375 bool post_update();
376
377+ void schedule_set_crtc();
378+
379 private:
380 BufferObject* get_front_buffer_object();
381 bool schedule_and_wait_for_page_flip(BufferObject* bufobj);
382@@ -68,6 +71,7 @@
383 GBMSurfaceUPtr surface_gbm;
384 helpers::EGLHelper egl;
385 geometry::Size size;
386+ std::atomic<bool> needs_set_crtc;
387 };
388
389 }
390
391=== modified file 'src/server/graphics/gbm/gbm_display_helpers.cpp'
392--- src/server/graphics/gbm/gbm_display_helpers.cpp 2013-03-13 04:54:15 +0000
393+++ src/server/graphics/gbm/gbm_display_helpers.cpp 2013-04-11 11:00:30 +0000
394@@ -96,6 +96,46 @@
395 }
396 }
397
398+void mggh::DRMHelper::drop_master() const
399+{
400+ /* We must have our own device fd first, so that it has become the DRM master */
401+ if (fd < 0)
402+ {
403+ BOOST_THROW_EXCEPTION(
404+ std::runtime_error("Tried to drop DRM master without a DRM device"));
405+ }
406+
407+ int ret = drmDropMaster(fd);
408+
409+ if (ret < 0)
410+ {
411+ BOOST_THROW_EXCEPTION(
412+ boost::enable_error_info(
413+ std::runtime_error("Failed to drop DRM master"))
414+ << boost::errinfo_errno(ret));
415+ }
416+}
417+
418+void mggh::DRMHelper::set_master() const
419+{
420+ /* We must have our own device fd first, so that it has become the DRM master */
421+ if (fd < 0)
422+ {
423+ BOOST_THROW_EXCEPTION(
424+ std::runtime_error("Tried to set DRM master without a DRM device"));
425+ }
426+
427+ int ret = drmSetMaster(fd);
428+
429+ if (ret < 0)
430+ {
431+ BOOST_THROW_EXCEPTION(
432+ boost::enable_error_info(
433+ std::runtime_error("Failed to set DRM master"))
434+ << boost::errinfo_errno(ret));
435+ }
436+}
437+
438 int mggh::DRMHelper::open_drm_device()
439 {
440 static const char *drivers[] = {
441
442=== modified file 'src/server/graphics/gbm/gbm_display_helpers.h'
443--- src/server/graphics/gbm/gbm_display_helpers.h 2013-03-21 03:32:59 +0000
444+++ src/server/graphics/gbm/gbm_display_helpers.h 2013-04-11 11:00:30 +0000
445@@ -57,6 +57,9 @@
446 int get_authenticated_fd();
447 void auth_magic(drm_magic_t magic) const;
448
449+ void drop_master() const;
450+ void set_master() const;
451+
452 int fd;
453
454 private:
455
456=== modified file 'src/server/graphics/gbm/gbm_platform.cpp'
457--- src/server/graphics/gbm/gbm_platform.cpp 2013-04-09 18:00:48 +0000
458+++ src/server/graphics/gbm/gbm_platform.cpp 2013-04-11 11:00:30 +0000
459@@ -21,6 +21,7 @@
460 #include <boost/throw_exception.hpp>
461 #include "gbm_buffer_allocator.h"
462 #include "gbm_display.h"
463+#include "linux_virtual_terminal.h"
464 #include "mir/graphics/platform_ipc_package.h"
465 #include "mir/graphics/egl/mesa_native_display.h"
466 #include "mir/logging/logger.h"
467@@ -54,9 +55,11 @@
468
469 }
470
471-mgg::GBMPlatform::GBMPlatform(std::shared_ptr<DisplayReport> const& listener) :
472- listener(listener),
473- native_display(0)
474+mgg::GBMPlatform::GBMPlatform(std::shared_ptr<DisplayReport> const& listener,
475+ std::shared_ptr<VirtualTerminal> const& vt)
476+ : listener(listener),
477+ vt{vt},
478+ native_display(0)
479 {
480 drm.setup();
481 gbm.setup(drm);
482@@ -97,5 +100,7 @@
483
484 std::shared_ptr<mg::Platform> mg::create_platform(std::shared_ptr<DisplayReport> const& report)
485 {
486- return std::make_shared<mgg::GBMPlatform>(report);
487+ return std::make_shared<mgg::GBMPlatform>(
488+ report,
489+ std::make_shared<mgg::LinuxVirtualTerminal>());
490 }
491
492=== modified file 'src/server/graphics/gbm/gbm_platform.h'
493--- src/server/graphics/gbm/gbm_platform.h 2013-04-09 18:00:48 +0000
494+++ src/server/graphics/gbm/gbm_platform.h 2013-04-11 11:00:30 +0000
495@@ -32,12 +32,15 @@
496 namespace gbm
497 {
498
499+class VirtualTerminal;
500+
501 class GBMPlatform : public Platform,
502 public DRMAuthenticator,
503 public std::enable_shared_from_this<GBMPlatform>
504 {
505 public:
506- explicit GBMPlatform(std::shared_ptr<DisplayReport> const& reporter);
507+ explicit GBMPlatform(std::shared_ptr<DisplayReport> const& reporter,
508+ std::shared_ptr<VirtualTerminal> const& vt);
509
510 /* From Platform */
511 std::shared_ptr<compositor::GraphicBufferAllocator> create_buffer_allocator(
512@@ -53,7 +56,9 @@
513 helpers::DRMHelper drm;
514 helpers::GBMHelper gbm;
515
516- std::shared_ptr<DisplayReport> listener;
517+ std::shared_ptr<DisplayReport> const listener;
518+ std::shared_ptr<VirtualTerminal> const vt;
519+
520 private:
521 std::shared_ptr<MirMesaEGLNativeDisplay> native_display;
522 };
523
524=== added file 'src/server/graphics/gbm/linux_virtual_terminal.cpp'
525--- src/server/graphics/gbm/linux_virtual_terminal.cpp 1970-01-01 00:00:00 +0000
526+++ src/server/graphics/gbm/linux_virtual_terminal.cpp 2013-04-11 11:00:30 +0000
527@@ -0,0 +1,180 @@
528+/*
529+ * Copyright © 2013 Canonical Ltd.
530+ *
531+ * This program is free software: you can redistribute it and/or modify it
532+ * under the terms of the GNU Lesser General Public License version 3,
533+ * as published by the Free Software Foundation.
534+ *
535+ * This program is distributed in the hope that it will be useful,
536+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
537+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
538+ * GNU General Public License for more details.
539+ *
540+ * You should have received a copy of the GNU Lesser General Public License
541+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
542+ *
543+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
544+ */
545+
546+#include "linux_virtual_terminal.h"
547+#include "mir/main_loop.h"
548+
549+#include <boost/throw_exception.hpp>
550+#include <boost/exception/errinfo_errno.hpp>
551+#include <boost/exception/errinfo_file_name.hpp>
552+
553+#include <vector>
554+#include <string>
555+#include <sstream>
556+#include <stdexcept>
557+#include <csignal>
558+
559+#include <fcntl.h>
560+#include <linux/vt.h>
561+#include <linux/kd.h>
562+#include <sys/ioctl.h>
563+
564+namespace mgg = mir::graphics::gbm;
565+
566+namespace
567+{
568+
569+int find_active_vt_number()
570+{
571+ static std::vector<std::string> const paths{"/dev/tty", "/dev/tty0"};
572+ int active_vt{-1};
573+
574+ for (auto& p : paths)
575+ {
576+ auto fd = open(p.c_str(), O_RDONLY, 0);
577+ if (fd < 0)
578+ fd = open(p.c_str(), O_WRONLY, 0);
579+
580+ if (fd >= 0)
581+ {
582+ struct vt_stat vts;
583+ auto status = ioctl(fd, VT_GETSTATE, &vts);
584+ close(fd);
585+
586+ if (status >= 0)
587+ {
588+ active_vt = vts.v_active;
589+ break;
590+ }
591+ }
592+ }
593+
594+ if (active_vt < 0)
595+ {
596+ BOOST_THROW_EXCEPTION(
597+ std::runtime_error("Failed to find the current VT"));
598+ }
599+
600+ return active_vt;
601+}
602+
603+int open_vt(int vt_number)
604+{
605+ std::stringstream vt_path_stream;
606+ vt_path_stream << "/dev/tty" << vt_number;
607+
608+ std::string const active_vt_path{vt_path_stream.str()};
609+
610+ auto vt_fd = open(active_vt_path.c_str(), O_RDONLY | O_NDELAY, 0);
611+
612+ if (vt_fd < 0)
613+ {
614+ BOOST_THROW_EXCEPTION(
615+ boost::enable_error_info(
616+ std::runtime_error("Failed to open current VT"))
617+ << boost::errinfo_file_name(active_vt_path)
618+ << boost::errinfo_errno(errno));
619+ }
620+
621+ return vt_fd;
622+}
623+
624+}
625+
626+mgg::LinuxVirtualTerminal::LinuxVirtualTerminal()
627+ : vt_fd{open_vt(find_active_vt_number())},
628+ prev_kd_mode{0},
629+ prev_vt_mode(),
630+ active{true}
631+{
632+ if (ioctl(vt_fd.fd(), KDGETMODE, &prev_kd_mode) < 0)
633+ {
634+ BOOST_THROW_EXCEPTION(
635+ boost::enable_error_info(
636+ std::runtime_error("Failed to get current VT mode"))
637+ << boost::errinfo_errno(errno));
638+ }
639+
640+ if (ioctl(vt_fd.fd(), VT_GETMODE, &prev_vt_mode) < 0)
641+ {
642+ BOOST_THROW_EXCEPTION(
643+ boost::enable_error_info(
644+ std::runtime_error("Failed to get the current VT")) << boost::errinfo_errno(errno));
645+ }
646+}
647+
648+mgg::LinuxVirtualTerminal::~LinuxVirtualTerminal() noexcept(true)
649+{
650+ if (vt_fd.fd() > 0)
651+ {
652+ ioctl(vt_fd.fd(), KDSETMODE, prev_kd_mode);
653+ ioctl(vt_fd.fd(), VT_SETMODE, &prev_vt_mode);
654+ }
655+}
656+
657+void mgg::LinuxVirtualTerminal::set_graphics_mode()
658+{
659+ if (ioctl(vt_fd.fd(), KDSETMODE, KD_GRAPHICS) < 0)
660+ {
661+ BOOST_THROW_EXCEPTION(
662+ boost::enable_error_info(
663+ std::runtime_error("Failed to set VT to graphics mode"))
664+ << boost::errinfo_errno(errno));
665+ }
666+}
667+
668+void mgg::LinuxVirtualTerminal::register_switch_handlers(
669+ MainLoop& main_loop,
670+ std::function<void()> const& switch_away,
671+ std::function<void()> const& switch_back)
672+{
673+ main_loop.register_signal_handler(
674+ {SIGUSR1},
675+ [this, switch_away, switch_back](int)
676+ {
677+ active = !active;
678+ if (active)
679+ {
680+ static int const allow_switch{2};
681+ switch_back();
682+ ioctl(vt_fd.fd(), VT_RELDISP, allow_switch);
683+ }
684+ else
685+ {
686+ switch_away();
687+ ioctl(vt_fd.fd(), VT_RELDISP, VT_ACKACQ);
688+ }
689+ });
690+
691+ struct vt_mode vtm
692+ {
693+ VT_PROCESS,
694+ 0,
695+ SIGUSR1,
696+ SIGUSR1,
697+ 0
698+ };
699+
700+ if (ioctl(vt_fd.fd(), VT_SETMODE, &vtm) < 0)
701+ {
702+ BOOST_THROW_EXCEPTION(
703+ boost::enable_error_info(
704+ std::runtime_error("Failed to set the current VT mode"))
705+ << boost::errinfo_errno(errno));
706+ }
707+}
708
709=== added file 'src/server/graphics/gbm/linux_virtual_terminal.h'
710--- src/server/graphics/gbm/linux_virtual_terminal.h 1970-01-01 00:00:00 +0000
711+++ src/server/graphics/gbm/linux_virtual_terminal.h 2013-04-11 11:00:30 +0000
712@@ -0,0 +1,67 @@
713+/*
714+ * Copyright © 2013 Canonical Ltd.
715+ *
716+ * This program is free software: you can redistribute it and/or modify it
717+ * under the terms of the GNU Lesser General Public License version 3,
718+ * as published by the Free Software Foundation.
719+ *
720+ * This program is distributed in the hope that it will be useful,
721+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
722+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
723+ * GNU General Public License for more details.
724+ *
725+ * You should have received a copy of the GNU Lesser General Public License
726+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
727+ *
728+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
729+ */
730+
731+#ifndef MIR_GRAPHICS_GBM_LINUX_VIRTUAL_TERMINAL_H_
732+#define MIR_GRAPHICS_GBM_LINUX_VIRTUAL_TERMINAL_H_
733+
734+#include "virtual_terminal.h"
735+
736+#include <linux/vt.h>
737+#include <unistd.h>
738+
739+namespace mir
740+{
741+namespace graphics
742+{
743+namespace gbm
744+{
745+
746+class LinuxVirtualTerminal : public VirtualTerminal
747+{
748+public:
749+ LinuxVirtualTerminal();
750+ ~LinuxVirtualTerminal() noexcept(true);
751+
752+ void set_graphics_mode();
753+ void register_switch_handlers(
754+ MainLoop& main_loop,
755+ std::function<void()> const& switch_away,
756+ std::function<void()> const& switch_back);
757+
758+private:
759+ class FDWrapper
760+ {
761+ public:
762+ FDWrapper(int fd) : fd_{fd} {}
763+ ~FDWrapper() { if (fd_ >= 0) close(fd_); }
764+ int fd() const { return fd_; }
765+ private:
766+ int const fd_;
767+ };
768+
769+ FDWrapper const vt_fd;
770+ int prev_kd_mode;
771+ struct vt_mode prev_vt_mode;
772+ bool active;
773+};
774+
775+}
776+}
777+}
778+
779+#endif /* MIR_GRAPHICS_GBM_LINUX_VIRTUAL_TERMINAL_H_ */
780
781=== added file 'src/server/graphics/gbm/virtual_terminal.h'
782--- src/server/graphics/gbm/virtual_terminal.h 1970-01-01 00:00:00 +0000
783+++ src/server/graphics/gbm/virtual_terminal.h 2013-04-11 11:00:30 +0000
784@@ -0,0 +1,55 @@
785+/*
786+ * Copyright © 2013 Canonical Ltd.
787+ *
788+ * This program is free software: you can redistribute it and/or modify it
789+ * under the terms of the GNU Lesser 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 Lesser 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_GRAPHICS_GBM_VIRTUAL_TERMINAL_H_
804+#define MIR_GRAPHICS_GBM_VIRTUAL_TERMINAL_H_
805+
806+#include <functional>
807+
808+namespace mir
809+{
810+
811+class MainLoop;
812+
813+namespace graphics
814+{
815+namespace gbm
816+{
817+
818+class VirtualTerminal
819+{
820+public:
821+ virtual ~VirtualTerminal() = default;
822+
823+ virtual void set_graphics_mode() = 0;
824+ virtual void register_switch_handlers(
825+ MainLoop& main_loop,
826+ std::function<void()> const& switch_away,
827+ std::function<void()> const& switch_back) = 0;
828+
829+protected:
830+ VirtualTerminal() = default;
831+ VirtualTerminal(VirtualTerminal const&) = delete;
832+ VirtualTerminal& operator=(VirtualTerminal const&) = delete;
833+};
834+
835+}
836+}
837+}
838+
839+#endif /* MIR_GRAPHICS_GBM_VIRTUAL_TERMINAL_H_ */
840
841=== modified file 'tests/behavior-tests/session_management_context.cpp'
842--- tests/behavior-tests/session_management_context.cpp 2013-04-01 16:11:03 +0000
843+++ tests/behavior-tests/session_management_context.cpp 2013-04-11 11:00:30 +0000
844@@ -105,6 +105,15 @@
845 return std::shared_ptr<mg::DisplayConfiguration>();
846 }
847
848+ void register_pause_resume_handlers(MainLoop&,
849+ std::function<void()> const&,
850+ std::function<void()> const&)
851+ {
852+ }
853+
854+ void pause() {}
855+ void resume() {}
856+
857 geom::Rectangle area;
858 };
859
860
861=== modified file 'tests/integration-tests/test_display_server_main_loop_events.cpp'
862--- tests/integration-tests/test_display_server_main_loop_events.cpp 2013-04-08 16:20:33 +0000
863+++ tests/integration-tests/test_display_server_main_loop_events.cpp 2013-04-11 11:00:30 +0000
864@@ -17,6 +17,8 @@
865 */
866
867 #include "mir/compositor/compositor.h"
868+#include "mir/graphics/display.h"
869+#include "mir/main_loop.h"
870
871 #include "mir_test_framework/testing_server_configuration.h"
872 #include "mir_test_doubles/mock_input_manager.h"
873@@ -30,6 +32,7 @@
874
875 namespace mi = mir::input;
876 namespace mc = mir::compositor;
877+namespace mg = mir::graphics;
878 namespace mtd = mir::test::doubles;
879 namespace mtf = mir_test_framework;
880
881@@ -43,6 +46,54 @@
882 MOCK_METHOD0(stop, void());
883 };
884
885+class MockDisplay : public mg::Display
886+{
887+public:
888+ MockDisplay(std::shared_ptr<mg::Display> const& display,
889+ int pause_signal, int resume_signal)
890+ : display{display},
891+ pause_signal{pause_signal},
892+ resume_signal{resume_signal}
893+ {
894+ }
895+
896+ mir::geometry::Rectangle view_area() const
897+ {
898+ return display->view_area();
899+ }
900+
901+ void for_each_display_buffer(std::function<void(mg::DisplayBuffer&)> const& f)
902+ {
903+ display->for_each_display_buffer(f);
904+ }
905+
906+ std::shared_ptr<mg::DisplayConfiguration> configuration()
907+ {
908+ return display->configuration();
909+ }
910+
911+ void register_pause_resume_handlers(
912+ mir::MainLoop& main_loop,
913+ std::function<void()> const& pause_handler,
914+ std::function<void()> const& resume_handler)
915+ {
916+ main_loop.register_signal_handler(
917+ {pause_signal},
918+ [pause_handler](int) { pause_handler(); });
919+ main_loop.register_signal_handler(
920+ {resume_signal},
921+ [resume_handler](int) { resume_handler(); });
922+ }
923+
924+ MOCK_METHOD0(pause, void());
925+ MOCK_METHOD0(resume, void());
926+
927+private:
928+ std::shared_ptr<mg::Display> const display;
929+ int const pause_signal;
930+ int const resume_signal;
931+};
932+
933 class ServerConfig : public mtf::TestingServerConfiguration
934 {
935 public:
936@@ -77,6 +128,66 @@
937 std::shared_ptr<MockCompositor> mock_compositor;
938 };
939
940+
941+class PauseResumeServerConfig : public mtf::TestingServerConfiguration
942+{
943+public:
944+ PauseResumeServerConfig()
945+ : pause_signal{SIGUSR1}, resume_signal{SIGUSR2}
946+ {
947+ }
948+
949+ std::shared_ptr<mg::Display> the_display() override
950+ {
951+ if (!mock_display)
952+ {
953+ auto display = mtf::TestingServerConfiguration::the_display();
954+ mock_display = std::make_shared<MockDisplay>(display,
955+ pause_signal,
956+ resume_signal);
957+ }
958+
959+ return mock_display;
960+ }
961+
962+ std::shared_ptr<mc::Compositor> the_compositor() override
963+ {
964+ if (!mock_compositor)
965+ mock_compositor = std::make_shared<MockCompositor>();
966+
967+ return mock_compositor;
968+ }
969+
970+ std::shared_ptr<MockDisplay> the_mock_display()
971+ {
972+ the_display();
973+ return mock_display;
974+ }
975+
976+ std::shared_ptr<MockCompositor> the_mock_compositor()
977+ {
978+ the_compositor();
979+ return mock_compositor;
980+ }
981+
982+ void emit_pause_event()
983+ {
984+ kill(getpid(), pause_signal);
985+ }
986+
987+ void emit_resume_event()
988+ {
989+ kill(getpid(), resume_signal);
990+ }
991+
992+private:
993+ std::shared_ptr<MockCompositor> mock_compositor;
994+ std::shared_ptr<MockDisplay> mock_display;
995+
996+ int const pause_signal;
997+ int const resume_signal;
998+};
999+
1000 }
1001
1002 TEST(DisplayServerMainLoopEvents, display_server_shuts_down_properly_on_sigint)
1003@@ -100,3 +211,70 @@
1004 kill(getpid(), SIGTERM);
1005 });
1006 }
1007+
1008+TEST(DisplayServerMainLoopEvents, display_server_components_pause_and_resume)
1009+{
1010+ using namespace testing;
1011+
1012+ PauseResumeServerConfig server_config;
1013+
1014+ auto mock_compositor = server_config.the_mock_compositor();
1015+ auto mock_display = server_config.the_mock_display();
1016+
1017+ {
1018+ InSequence s;
1019+
1020+ /* Start */
1021+ EXPECT_CALL(*mock_compositor, start()).Times(1);
1022+
1023+ /* Pause */
1024+ EXPECT_CALL(*mock_compositor, stop()).Times(1);
1025+ EXPECT_CALL(*mock_display, pause()).Times(1);
1026+
1027+ /* Resume */
1028+ EXPECT_CALL(*mock_display, resume()).Times(1);
1029+ EXPECT_CALL(*mock_compositor, start()).Times(1);
1030+
1031+ /* Stop */
1032+ EXPECT_CALL(*mock_compositor, stop()).Times(1);
1033+ }
1034+
1035+ mir::run_mir(server_config,
1036+ [&server_config](mir::DisplayServer&)
1037+ {
1038+ server_config.emit_pause_event();
1039+ server_config.emit_resume_event();
1040+ kill(getpid(), SIGTERM);
1041+ });
1042+}
1043+
1044+TEST(DisplayServerMainLoopEvents, display_server_quits_when_paused)
1045+{
1046+ using namespace testing;
1047+
1048+ PauseResumeServerConfig server_config;
1049+
1050+ auto mock_compositor = server_config.the_mock_compositor();
1051+ auto mock_display = server_config.the_mock_display();
1052+
1053+ {
1054+ InSequence s;
1055+
1056+ /* Start */
1057+ EXPECT_CALL(*mock_compositor, start()).Times(1);
1058+
1059+ /* Pause */
1060+ EXPECT_CALL(*mock_compositor, stop()).Times(1);
1061+ EXPECT_CALL(*mock_display, pause()).Times(1);
1062+
1063+ /* Stop */
1064+ EXPECT_CALL(*mock_compositor, stop()).Times(1);
1065+ }
1066+
1067+ mir::run_mir(server_config,
1068+ [&server_config](mir::DisplayServer&)
1069+ {
1070+ server_config.emit_pause_event();
1071+ kill(getpid(), SIGTERM);
1072+ });
1073+}
1074
1075=== modified file 'tests/integration-tests/test_surfaceloop.cpp'
1076--- tests/integration-tests/test_surfaceloop.cpp 2013-04-10 16:40:04 +0000
1077+++ tests/integration-tests/test_surfaceloop.cpp 2013-04-11 11:00:30 +0000
1078@@ -133,6 +133,13 @@
1079 auto null_configuration = std::shared_ptr<mg::DisplayConfiguration>();
1080 return null_configuration;
1081 }
1082+ void register_pause_resume_handlers(mir::MainLoop&,
1083+ std::function<void()> const&,
1084+ std::function<void()> const&)
1085+ {
1086+ }
1087+ void pause() {}
1088+ void resume() {}
1089 };
1090
1091 struct SurfaceSync
1092
1093=== modified file 'tests/mir_test_framework/testing_server_options.cpp'
1094--- tests/mir_test_framework/testing_server_options.cpp 2013-04-09 18:00:48 +0000
1095+++ tests/mir_test_framework/testing_server_options.cpp 2013-04-11 11:00:30 +0000
1096@@ -86,6 +86,13 @@
1097 auto null_configuration = std::shared_ptr<mg::DisplayConfiguration>();
1098 return null_configuration;
1099 }
1100+ void register_pause_resume_handlers(mir::MainLoop&,
1101+ std::function<void()> const&,
1102+ std::function<void()> const&)
1103+ {
1104+ }
1105+ void pause() {}
1106+ void resume() {}
1107 };
1108
1109 class StubGraphicPlatform : public mg::Platform
1110
1111=== modified file 'tests/unit-tests/compositor/test_multi_threaded_compositor.cpp'
1112--- tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2013-03-27 15:12:09 +0000
1113+++ tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2013-04-11 11:00:30 +0000
1114@@ -53,6 +53,13 @@
1115 {
1116 return std::shared_ptr<mg::DisplayConfiguration>();
1117 }
1118+ void register_pause_resume_handlers(mir::MainLoop&,
1119+ std::function<void()> const&,
1120+ std::function<void()> const&)
1121+ {
1122+ }
1123+ void pause() {}
1124+ void resume() {}
1125
1126 private:
1127 std::vector<mtd::NullDisplayBuffer> buffers;
1128
1129=== modified file 'tests/unit-tests/graphics/gbm/mock_drm.cpp'
1130--- tests/unit-tests/graphics/gbm/mock_drm.cpp 2013-03-07 06:00:18 +0000
1131+++ tests/unit-tests/graphics/gbm/mock_drm.cpp 2013-04-11 11:00:30 +0000
1132@@ -351,3 +351,13 @@
1133 {
1134 return global_mock->drmPrimeFDToHandle(fd, prime_fd, handle);
1135 }
1136+
1137+int drmSetMaster(int fd)
1138+{
1139+ return global_mock->drmSetMaster(fd);
1140+}
1141+
1142+int drmDropMaster(int fd)
1143+{
1144+ return global_mock->drmDropMaster(fd);
1145+}
1146
1147=== modified file 'tests/unit-tests/graphics/gbm/mock_drm.h'
1148--- tests/unit-tests/graphics/gbm/mock_drm.h 2013-03-07 06:00:18 +0000
1149+++ tests/unit-tests/graphics/gbm/mock_drm.h 2013-04-11 11:00:30 +0000
1150@@ -117,6 +117,9 @@
1151 MOCK_METHOD4(drmPrimeHandleToFD, int(int fd, uint32_t handle, uint32_t flags, int *prime_fd));
1152 MOCK_METHOD3(drmPrimeFDToHandle, int(int fd, int prime_fd, uint32_t *handle));
1153
1154+ MOCK_METHOD1(drmSetMaster, int(int fd));
1155+ MOCK_METHOD1(drmDropMaster, int(int fd));
1156+
1157 FakeDRMResources fake_drm;
1158 };
1159
1160
1161=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_buffer.cpp'
1162--- tests/unit-tests/graphics/gbm/test_gbm_buffer.cpp 2013-03-27 04:39:27 +0000
1163+++ tests/unit-tests/graphics/gbm/test_gbm_buffer.cpp 2013-04-11 11:00:30 +0000
1164@@ -27,6 +27,7 @@
1165 #include "mir/graphics/buffer_initializer.h"
1166 #include "mir/compositor/buffer_ipc_package.h"
1167 #include "mir/compositor/buffer_properties.h"
1168+#include "mir_test_doubles/null_virtual_terminal.h"
1169
1170 #include "mir/graphics/null_display_report.h"
1171
1172@@ -42,6 +43,7 @@
1173 namespace mg=mir::graphics;
1174 namespace mgg=mir::graphics::gbm;
1175 namespace geom=mir::geometry;
1176+namespace mtd=mir::test::doubles;
1177
1178 class GBMGraphicBufferBasic : public ::testing::Test
1179 {
1180@@ -77,7 +79,8 @@
1181 ON_CALL(mock_egl, eglGetProcAddress(StrEq("glEGLImageTargetTexture2DOES")))
1182 .WillByDefault(Return(reinterpret_cast<func_ptr_t>(glEGLImageTargetTexture2DOES)));
1183
1184- platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1185+ platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>(),
1186+ std::make_shared<mtd::NullVirtualTerminal>());
1187 null_init = std::make_shared<mg::NullBufferInitializer>();
1188 allocator.reset(new mgg::GBMBufferAllocator(platform, null_init));
1189 }
1190
1191=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_buffer_allocator.cpp'
1192--- tests/unit-tests/graphics/gbm/test_gbm_buffer_allocator.cpp 2013-03-13 08:09:52 +0000
1193+++ tests/unit-tests/graphics/gbm/test_gbm_buffer_allocator.cpp 2013-04-11 11:00:30 +0000
1194@@ -27,6 +27,7 @@
1195 #include "mir_test/egl_mock.h"
1196 #include "mir_test/gl_mock.h"
1197 #include "mir_test_doubles/mock_buffer_initializer.h"
1198+#include "mir_test_doubles/null_virtual_terminal.h"
1199 #include "mir/graphics/null_display_report.h"
1200
1201 #include <memory>
1202@@ -67,7 +68,8 @@
1203 ON_CALL(mock_egl, eglGetProcAddress(StrEq("glEGLImageTargetTexture2DOES")))
1204 .WillByDefault(Return(reinterpret_cast<func_ptr_t>(glEGLImageTargetTexture2DOES)));
1205
1206- platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1207+ platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>(),
1208+ std::make_shared<mtd::NullVirtualTerminal>());
1209 mock_buffer_initializer = std::make_shared<testing::NiceMock<mtd::MockBufferInitializer>>();
1210 allocator.reset(new mgg::GBMBufferAllocator(platform, mock_buffer_initializer));
1211 }
1212
1213=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_display.cpp'
1214--- tests/unit-tests/graphics/gbm/test_gbm_display.cpp 2013-03-22 11:37:34 +0000
1215+++ tests/unit-tests/graphics/gbm/test_gbm_display.cpp 2013-04-11 11:00:30 +0000
1216@@ -18,13 +18,17 @@
1217 #include <boost/throw_exception.hpp>
1218 #include "src/server/graphics/gbm/gbm_platform.h"
1219 #include "src/server/graphics/gbm/gbm_display.h"
1220+#include "src/server/graphics/gbm/virtual_terminal.h"
1221 #include "mir/logging/display_report.h"
1222 #include "mir/logging/logger.h"
1223+#include "mir/graphics/display_buffer.h"
1224+#include "mir/main_loop.h"
1225
1226 #include "mir_test/egl_mock.h"
1227 #include "mir_test/gl_mock.h"
1228 #include "mir/graphics/null_display_report.h"
1229 #include "mir_test_doubles/mock_display_report.h"
1230+#include "mir_test_doubles/null_virtual_terminal.h"
1231
1232 #include "mock_drm.h"
1233 #include "mock_gbm.h"
1234@@ -48,11 +52,24 @@
1235 ~MockLogger() noexcept(true) {}
1236 };
1237
1238+class MockVirtualTerminal : public mgg::VirtualTerminal
1239+{
1240+public:
1241+ ~MockVirtualTerminal() noexcept(true) {}
1242+
1243+ MOCK_METHOD0(set_graphics_mode, void());
1244+ MOCK_METHOD3(register_switch_handlers,
1245+ void(mir::MainLoop&,
1246+ std::function<void()> const&,
1247+ std::function<void()> const&));
1248+};
1249+
1250 class GBMDisplayTest : public ::testing::Test
1251 {
1252 public:
1253 GBMDisplayTest() :
1254- mock_report(new ::testing::NiceMock<mtd::MockDisplayReport>())
1255+ mock_report{std::make_shared<testing::NiceMock<mtd::MockDisplayReport>>()},
1256+ null_report{std::make_shared<mg::NullDisplayReport>()}
1257 {
1258 using namespace testing;
1259 ON_CALL(mock_egl, eglChooseConfig(_,_,_,1,_))
1260@@ -78,6 +95,12 @@
1261 .Times(AtLeast(0));
1262 }
1263
1264+ std::shared_ptr<mgg::GBMPlatform> create_platform()
1265+ {
1266+ return std::make_shared<mgg::GBMPlatform>(
1267+ null_report,
1268+ std::make_shared<mtd::NullVirtualTerminal>());
1269+ }
1270
1271 void setup_post_update_expectations()
1272 {
1273@@ -167,7 +190,8 @@
1274 ::testing::NiceMock<mir::GLMock> mock_gl;
1275 ::testing::NiceMock<mgg::MockDRM> mock_drm;
1276 ::testing::NiceMock<mgg::MockGBM> mock_gbm;
1277- std::shared_ptr<testing::NiceMock<mtd::MockDisplayReport>> mock_report;
1278+ std::shared_ptr<testing::NiceMock<mtd::MockDisplayReport>> const mock_report;
1279+ std::shared_ptr<mg::DisplayReport> const null_report;
1280 };
1281
1282 }
1283@@ -232,8 +256,8 @@
1284
1285 EXPECT_NO_THROW(
1286 {
1287- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1288- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1289+ auto platform = create_platform();
1290+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1291 });
1292 }
1293
1294@@ -273,8 +297,8 @@
1295
1296 EXPECT_NO_THROW(
1297 {
1298- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1299- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1300+ auto platform = create_platform();
1301+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1302 });
1303 }
1304
1305@@ -291,8 +315,8 @@
1306
1307 EXPECT_THROW(
1308 {
1309- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1310- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1311+ auto platform = create_platform();
1312+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1313 }, std::runtime_error);
1314 }
1315
1316@@ -310,10 +334,10 @@
1317 EXPECT_CALL(mock_drm, drmClose(_))
1318 .Times(Exactly(1));
1319
1320- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1321+ auto platform = create_platform();
1322
1323 EXPECT_THROW({
1324- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1325+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1326 }, std::runtime_error) << "Expected that c'tor of GBMDisplay throws";
1327 }
1328
1329@@ -332,8 +356,8 @@
1330 .Times(Exactly(1));
1331
1332 EXPECT_THROW({
1333- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1334- }, std::runtime_error) << "Expected c'tor of GBMDisplay to throw an exception";
1335+ auto platform = create_platform();
1336+ }, std::runtime_error) << "Expected c'tor of GBMPlatform to throw an exception";
1337 }
1338
1339 namespace
1340@@ -394,8 +418,8 @@
1341
1342 EXPECT_NO_THROW(
1343 {
1344- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1345- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1346+ auto platform = create_platform();
1347+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1348
1349 display->for_each_display_buffer([](mg::DisplayBuffer& db)
1350 {
1351@@ -434,8 +458,8 @@
1352
1353 EXPECT_NO_THROW(
1354 {
1355- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1356- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1357+ auto platform = create_platform();
1358+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1359
1360 display->for_each_display_buffer([](mg::DisplayBuffer& db)
1361 {
1362@@ -469,7 +493,7 @@
1363
1364 EXPECT_NO_THROW(
1365 {
1366- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1367+ auto platform = create_platform();
1368 auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1369 });
1370 }
1371@@ -478,11 +502,11 @@
1372 {
1373 using namespace ::testing;
1374
1375- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1376+ auto platform = create_platform();
1377 auto logger = std::make_shared<MockLogger>();
1378
1379 auto reporter = std::make_shared<ml::DisplayReport>(logger);
1380- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1381+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1382
1383 EXPECT_CALL(
1384 *logger,
1385@@ -497,11 +521,11 @@
1386 {
1387 using namespace ::testing;
1388
1389- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1390+ auto platform = create_platform();
1391 auto logger = std::make_shared<MockLogger>();
1392
1393 auto reporter = std::make_shared<ml::DisplayReport>(logger);
1394- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1395+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1396
1397 EXPECT_CALL(
1398 *logger,
1399@@ -516,11 +540,11 @@
1400 {
1401 using namespace ::testing;
1402
1403- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1404+ auto platform = create_platform();
1405 auto logger = std::make_shared<MockLogger>();
1406
1407 auto reporter = std::make_shared<ml::DisplayReport>(logger);
1408- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1409+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1410
1411 EXPECT_CALL(
1412 *logger,
1413@@ -535,11 +559,11 @@
1414 {
1415 using namespace ::testing;
1416
1417- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1418+ auto platform = create_platform();
1419 auto logger = std::make_shared<MockLogger>();
1420
1421 auto reporter = std::make_shared<ml::DisplayReport>(logger);
1422- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1423+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1424
1425 EXPECT_CALL(
1426 *logger,
1427@@ -561,8 +585,8 @@
1428
1429 EXPECT_THROW(
1430 {
1431- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1432- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1433+ auto platform = create_platform();
1434+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1435 }, std::runtime_error);
1436 }
1437
1438@@ -577,8 +601,8 @@
1439
1440 EXPECT_THROW(
1441 {
1442- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1443- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1444+ auto platform = create_platform();
1445+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1446 }, std::runtime_error);
1447 }
1448
1449@@ -586,8 +610,8 @@
1450 {
1451 using namespace ::testing;
1452
1453- auto platform = std::make_shared<mgg::GBMPlatform>(std::make_shared<mg::NullDisplayReport>());
1454- auto display = std::make_shared<mgg::GBMDisplay>(platform, mock_report);
1455+ auto platform = create_platform();
1456+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1457
1458 int callback_count{0};
1459
1460@@ -598,3 +622,65 @@
1461
1462 EXPECT_NE(0, callback_count);
1463 }
1464+
1465+TEST_F(GBMDisplayTest, constructor_sets_vt_graphics_mode)
1466+{
1467+ using namespace testing;
1468+
1469+ auto mock_vt = std::make_shared<MockVirtualTerminal>();
1470+
1471+ EXPECT_CALL(*mock_vt, set_graphics_mode())
1472+ .Times(1);
1473+
1474+ auto platform = std::make_shared<mgg::GBMPlatform>(null_report, mock_vt);
1475+
1476+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1477+}
1478+
1479+TEST_F(GBMDisplayTest, pause_drops_drm_master)
1480+{
1481+ using namespace testing;
1482+
1483+ EXPECT_CALL(mock_drm, drmDropMaster(mock_drm.fake_drm.fd()))
1484+ .Times(1);
1485+
1486+ auto platform = create_platform();
1487+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1488+
1489+ display->pause();
1490+}
1491+
1492+TEST_F(GBMDisplayTest, resume_sets_drm_master)
1493+{
1494+ using namespace testing;
1495+
1496+ EXPECT_CALL(mock_drm, drmSetMaster(mock_drm.fake_drm.fd()))
1497+ .Times(1);
1498+
1499+ auto platform = create_platform();
1500+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1501+
1502+ display->resume();
1503+}
1504+
1505+TEST_F(GBMDisplayTest, set_or_drop_drm_master_failure_throws)
1506+{
1507+ using namespace testing;
1508+
1509+ EXPECT_CALL(mock_drm, drmDropMaster(_))
1510+ .WillOnce(Return(-1));
1511+
1512+ EXPECT_CALL(mock_drm, drmSetMaster(_))
1513+ .WillOnce(Return(-1));
1514+
1515+ auto platform = create_platform();
1516+ auto display = std::make_shared<mgg::GBMDisplay>(platform, null_report);
1517+
1518+ EXPECT_THROW({
1519+ display->pause();
1520+ }, std::runtime_error);
1521+
1522+ EXPECT_THROW({
1523+ display->resume();
1524+ }, std::runtime_error);
1525+}
1526
1527=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp'
1528--- tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp 2013-03-13 08:09:52 +0000
1529+++ tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp 2013-04-11 11:00:30 +0000
1530@@ -25,6 +25,7 @@
1531 #include "mir_test/egl_mock.h"
1532 #include "mir_test/gl_mock.h"
1533 #include "mir/graphics/null_display_report.h"
1534+#include "mir_test_doubles/null_virtual_terminal.h"
1535
1536 #include "mock_drm.h"
1537 #include "mock_gbm.h"
1538@@ -37,6 +38,7 @@
1539 namespace mg = mir::graphics;
1540 namespace mgg = mir::graphics::gbm;
1541 namespace geom = mir::geometry;
1542+namespace mtd = mir::test::doubles;
1543
1544 namespace
1545 {
1546@@ -59,8 +61,7 @@
1547 class GBMDisplayConfigurationTest : public ::testing::Test
1548 {
1549 public:
1550- GBMDisplayConfigurationTest() :
1551- null_listener{std::make_shared<mg::NullDisplayReport>()}
1552+ GBMDisplayConfigurationTest()
1553 {
1554 using namespace testing;
1555
1556@@ -81,6 +82,13 @@
1557 setup_sample_modes();
1558 }
1559
1560+ std::shared_ptr<mgg::GBMPlatform> create_platform()
1561+ {
1562+ return std::make_shared<mgg::GBMPlatform>(
1563+ std::make_shared<mg::NullDisplayReport>(),
1564+ std::make_shared<mtd::NullVirtualTerminal>());
1565+ }
1566+
1567 void setup_sample_modes()
1568 {
1569 /* Add DRM modes */
1570@@ -98,7 +106,6 @@
1571 ::testing::NiceMock<mir::GLMock> mock_gl;
1572 ::testing::NiceMock<mgg::MockDRM> mock_drm;
1573 ::testing::NiceMock<mgg::MockGBM> mock_gbm;
1574- std::shared_ptr<mg::DisplayReport> const null_listener;
1575
1576 std::vector<drmModeModeInfo> modes0;
1577 std::vector<mg::DisplayConfigurationMode> conf_modes0;
1578@@ -176,7 +183,7 @@
1579 };
1580
1581 /* Test body */
1582- auto platform = std::make_shared<mgg::GBMPlatform>(null_listener);
1583+ auto platform = create_platform();
1584 auto display = platform->create_display();
1585
1586 auto conf = display->configuration();
1587@@ -214,7 +221,7 @@
1588 resources.prepare();
1589
1590 /* Test body */
1591- auto platform = std::make_shared<mgg::GBMPlatform>(null_listener);
1592+ auto platform = create_platform();
1593 auto display = platform->create_display();
1594
1595 auto conf = display->configuration();
1596@@ -253,7 +260,7 @@
1597 resources.prepare();
1598
1599 /* Test body */
1600- auto platform = std::make_shared<mgg::GBMPlatform>(null_listener);
1601+ auto platform = create_platform();
1602 auto display = platform->create_display();
1603
1604 auto conf = display->configuration();
1605
1606=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp'
1607--- tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp 2013-03-13 08:09:52 +0000
1608+++ tests/unit-tests/graphics/gbm/test_gbm_display_multi_monitor.cpp 2013-04-11 11:00:30 +0000
1609@@ -23,6 +23,7 @@
1610 #include "mir_test/egl_mock.h"
1611 #include "mir_test/gl_mock.h"
1612 #include "mir/graphics/null_display_report.h"
1613+#include "mir_test_doubles/null_virtual_terminal.h"
1614
1615 #include "mock_drm.h"
1616 #include "mock_gbm.h"
1617@@ -33,6 +34,7 @@
1618 namespace mg = mir::graphics;
1619 namespace mgg = mir::graphics::gbm;
1620 namespace geom = mir::geometry;
1621+namespace mtd = mir::test::doubles;
1622
1623 namespace
1624 {
1625@@ -41,7 +43,6 @@
1626 {
1627 public:
1628 GBMDisplayMultiMonitorTest()
1629- : null_listener{std::make_shared<mg::NullDisplayReport>()}
1630 {
1631 using namespace testing;
1632
1633@@ -69,6 +70,13 @@
1634 .Times(AtLeast(0));
1635 }
1636
1637+ std::shared_ptr<mgg::GBMPlatform> create_platform()
1638+ {
1639+ return std::make_shared<mgg::GBMPlatform>(
1640+ std::make_shared<mg::NullDisplayReport>(),
1641+ std::make_shared<mtd::NullVirtualTerminal>());
1642+ }
1643+
1644 void setup_outputs(int n)
1645 {
1646 mgg::FakeDRMResources& resources(mock_drm.fake_drm);
1647@@ -117,7 +125,6 @@
1648 testing::NiceMock<mir::GLMock> mock_gl;
1649 testing::NiceMock<mgg::MockDRM> mock_drm;
1650 testing::NiceMock<mgg::MockGBM> mock_gbm;
1651- std::shared_ptr<mg::DisplayReport> const null_listener;
1652
1653 std::vector<drmModeModeInfo> modes0;
1654 std::vector<drmModeModeInfo> modes_empty;
1655@@ -168,7 +175,7 @@
1656 .After(crtc_setups);
1657 }
1658
1659- auto platform = std::make_shared<mgg::GBMPlatform>(null_listener);
1660+ auto platform = create_platform();
1661 auto display = platform->create_display();
1662 }
1663
1664@@ -201,7 +208,7 @@
1665 .Times(1);
1666 }
1667
1668- auto platform = std::make_shared<mgg::GBMPlatform>(null_listener);
1669+ auto platform = create_platform();
1670 auto display = platform->create_display();
1671 }
1672
1673@@ -254,7 +261,7 @@
1674 .WillOnce(DoAll(InvokePageFlipHandler(&user_data[1]), Return(0)))
1675 .WillOnce(DoAll(InvokePageFlipHandler(&user_data[2]), Return(0)));
1676
1677- auto platform = std::make_shared<mgg::GBMPlatform>(null_listener);
1678+ auto platform = create_platform();
1679 auto display = platform->create_display();
1680
1681 display->for_each_display_buffer([](mg::DisplayBuffer& buffer)
1682
1683=== modified file 'tests/unit-tests/graphics/gbm/test_gbm_platform.cpp'
1684--- tests/unit-tests/graphics/gbm/test_gbm_platform.cpp 2013-03-13 04:54:15 +0000
1685+++ tests/unit-tests/graphics/gbm/test_gbm_platform.cpp 2013-04-11 11:00:30 +0000
1686@@ -16,9 +16,10 @@
1687 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
1688 */
1689
1690-#include "mir/graphics/platform.h"
1691 #include "mir/graphics/platform_ipc_package.h"
1692 #include "mir/graphics/drm_authenticator.h"
1693+#include "src/server/graphics/gbm/gbm_platform.h"
1694+#include "mir_test_doubles/null_virtual_terminal.h"
1695
1696 #include "mir/graphics/null_display_report.h"
1697
1698@@ -28,13 +29,17 @@
1699 #include "mock_gbm.h"
1700
1701 #include <gtest/gtest.h>
1702+#include <gmock/gmock.h>
1703
1704 #include <stdexcept>
1705
1706 namespace mg = mir::graphics;
1707+namespace mgg = mir::graphics::gbm;
1708+namespace mtd = mir::test::doubles;
1709
1710 namespace
1711 {
1712+
1713 class GBMGraphicsPlatform : public ::testing::Test
1714 {
1715 public:
1716@@ -43,6 +48,14 @@
1717 ::testing::Mock::VerifyAndClearExpectations(&mock_drm);
1718 ::testing::Mock::VerifyAndClearExpectations(&mock_gbm);
1719 }
1720+
1721+ std::shared_ptr<mg::Platform> create_platform()
1722+ {
1723+ return std::make_shared<mgg::GBMPlatform>(
1724+ std::make_shared<mg::NullDisplayReport>(),
1725+ std::make_shared<mtd::NullVirtualTerminal>());
1726+ }
1727+
1728 ::testing::NiceMock<mg::gbm::MockDRM> mock_drm;
1729 ::testing::NiceMock<mg::gbm::MockGBM> mock_gbm;
1730 };
1731@@ -69,7 +82,7 @@
1732 EXPECT_CALL(mock_drm, drmClose(auth_fd));
1733
1734 EXPECT_NO_THROW (
1735- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1736+ auto platform = create_platform();
1737 auto pkg = platform->get_ipc_package();
1738
1739 ASSERT_TRUE(pkg.get());
1740@@ -87,7 +100,7 @@
1741
1742 try
1743 {
1744- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1745+ auto platform = create_platform();
1746 } catch(...)
1747 {
1748 return;
1749@@ -105,7 +118,7 @@
1750 EXPECT_CALL(mock_drm, drmAuthMagic(mock_drm.fake_drm.fd(),magic))
1751 .WillOnce(Return(0));
1752
1753- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1754+ auto platform = create_platform();
1755 auto authenticator = std::dynamic_pointer_cast<mg::DRMAuthenticator>(platform);
1756 authenticator->drm_auth_magic(magic);
1757 }
1758@@ -119,7 +132,7 @@
1759 EXPECT_CALL(mock_drm, drmAuthMagic(mock_drm.fake_drm.fd(),magic))
1760 .WillOnce(Return(-1));
1761
1762- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1763+ auto platform = create_platform();
1764 auto authenticator = std::dynamic_pointer_cast<mg::DRMAuthenticator>(platform);
1765
1766 EXPECT_THROW({
1767
1768=== modified file 'tests/unit-tests/graphics/test_graphics_platform.cpp'
1769--- tests/unit-tests/graphics/test_graphics_platform.cpp 2013-03-22 17:08:01 +0000
1770+++ tests/unit-tests/graphics/test_graphics_platform.cpp 2013-04-11 11:00:30 +0000
1771@@ -25,6 +25,8 @@
1772 #ifndef ANDROID
1773 #include "gbm/mock_drm.h"
1774 #include "gbm/mock_gbm.h"
1775+#include "mir_test_doubles/null_virtual_terminal.h"
1776+#include "src/server/graphics/gbm/gbm_platform.h"
1777 #else
1778 #include "mir_test/hw_mock.h"
1779 #endif
1780@@ -69,6 +71,17 @@
1781 #endif
1782 }
1783
1784+ std::shared_ptr<mg::Platform> create_platform()
1785+ {
1786+#ifdef ANDROID
1787+ return mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1788+#else
1789+ return std::make_shared<mg::gbm::GBMPlatform>(
1790+ std::make_shared<mg::NullDisplayReport>(),
1791+ std::make_shared<mir::test::doubles::NullVirtualTerminal>());
1792+#endif
1793+ }
1794+
1795 std::shared_ptr<ml::Logger> logger;
1796 std::shared_ptr<mg::BufferInitializer> buffer_initializer;
1797
1798@@ -87,7 +100,7 @@
1799 using namespace testing;
1800
1801 EXPECT_NO_THROW (
1802- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1803+ auto platform = create_platform();
1804 auto allocator = platform->create_buffer_allocator(buffer_initializer);
1805
1806 EXPECT_TRUE(allocator.get());
1807@@ -97,7 +110,7 @@
1808
1809 TEST_F(GraphicsPlatform, buffer_creation)
1810 {
1811- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1812+ auto platform = create_platform();
1813 auto allocator = platform->create_buffer_allocator(buffer_initializer);
1814 auto supported_pixel_formats = allocator->supported_pixel_formats();
1815
1816@@ -119,7 +132,7 @@
1817
1818 TEST_F(GraphicsPlatform, get_ipc_package)
1819 {
1820- auto platform = mg::create_platform(std::make_shared<mg::NullDisplayReport>());
1821+ auto platform = create_platform();
1822 auto pkg = platform->get_ipc_package();
1823
1824 ASSERT_TRUE(pkg.get() != NULL);

Subscribers

People subscribed via source and target branches