Mir

Merge lp:~kdub/mir/require-streams-when-creating-surface into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 3453
Proposed branch: lp:~kdub/mir/require-streams-when-creating-surface
Merge into: lp:mir
Prerequisite: lp:~kdub/mir/deprecate-next-buffer
Diff against target: 1228 lines (+343/-184)
16 files modified
examples/server_example_canonical_window_manager.cpp (+9/-3)
examples/server_example_window_management_info.h (+1/-0)
include/server/mir/scene/surface_creation_parameters.h (+1/-0)
src/client/mir_connection.cpp (+17/-1)
src/protobuf/mir_protobuf.proto (+1/-0)
src/server/frontend/buffer_stream_tracker.cpp (+24/-0)
src/server/frontend/buffer_stream_tracker.h (+7/-0)
src/server/frontend/session_mediator.cpp (+66/-18)
src/server/scene/application_session.cpp (+31/-27)
src/server/scene/application_session.h (+2/-0)
tests/integration-tests/session_management.cpp (+7/-2)
tests/integration-tests/test_session.cpp (+5/-1)
tests/unit-tests/frontend/test_session_mediator.cpp (+40/-56)
tests/unit-tests/scene/test_abstract_shell.cpp (+47/-21)
tests/unit-tests/scene/test_application_session.cpp (+80/-54)
tests/unit-tests/scene/test_session_manager.cpp (+5/-1)
To merge this branch: bzr merge lp:~kdub/mir/require-streams-when-creating-surface
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Andreas Pokorny (community) Approve
Cemil Azizoglu (community) Approve
Brandon Schaefer (community) Approve
Review via email: mp+290484@code.launchpad.net

Commit message

shell: no longer auto-create a 'default stream' on behalf of user creating a surface without specifying a stream. Session::create_surface() was creating two resources, and we were kludging around this by casting the mf::SurfaceId it returns to a mf::BufferStreamId, and assuming that the stream was created.

Now, BufferStreamId and SurfaceId are independent id sequences (whereas previously, every SurfaceId was a BufferStreamId, but not vice-versa)

We got into the situation where create_surface() creates a stream and a surface when we split the stream concept from the surface concept a long time ago. Now that we want to create more elaborate stream configurations at startup (see lp: #1563278), we should just have the user tell us what they want via SurfaceCreationParameters instead of guessing and trying to compensate with an automatically created stream.

Its currently necessary to have some content with a Surface (due to existing interfaces that need changing), but soon enough we could probably have content-less surfaces, if that's useful anywhere...

Downstreams (usc/qtmir) are not using Session to create their own surfaces apart from actual ipc clients, so although its an ABI break, they should be compatible.

Description of the change

shell: no longer auto-create a 'default stream' on behalf of user creating a surface without specifying a stream. Session::create_surface() was creating two resources, and we were kludging around this by casting the mf::SurfaceId it returns to a mf::BufferStreamId, and assuming that the stream was created.

We got into the situation where create_surface() creates a stream and a surface when we split the stream concept from the surface concept a long time ago. Now that we want to create more elaborate stream configurations at startup (see lp: #1563278), we should just have the user tell us what they want via SurfaceCreationParameters instead of guessing and trying to compensate with an automatically created stream.

Its currently necessary to have some content with a Surface (due to existing interfaces that need changing), but soon enough we could probably have content-less surfaces, if that's useful anywhere...

Downstreams (usc/qtmir) are not using Session to create their own surfaces apart from actual ipc clients, so although its an ABI break, they should be compatible.

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

FAILED: Continuous integration, rev:3440
https://mir-jenkins.ubuntu.com/job/mir-ci/701/
Executed test runs:

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

conflict

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

PASSED: Continuous integration, rev:3443
https://mir-jenkins.ubuntu.com/job/mir-ci/734/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/701
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/738
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/729
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/729
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/710
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/710/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/710
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/710/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/710
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/710/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/710
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/710/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/710
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/710/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Nit. Couldnt a_surface() take a mir::graphics::BufferProperties? Since we use all the same arguments in both. Such as of_buffer_properties(...) or something... though either way we have to use those values twice :)
+ auto params = ms::a_surface()

Dont see this namespace used in the header.
+class Session;

Shared ptr are defaulted to a nullptr, no need to set it.
+ std::shared_ptr<mf::BufferStream> legacy_stream = nullptr;

// /usr/include/c++/5/tr1/shared_ptr.h:546
      __shared_ptr()
      : _M_ptr(0), _M_refcount() // never throws
      { }

This could be a bit simpler, as you have right now:
!(A || (B && C))
This could turn into:
!A && (B || C)

(wanted to do a truth table just to check haha: http://paste.ubuntu.com/15635820/)

Not super sure if its *simpler* just reads a bit easier :)

+ if (!((the_params.content_id.is_set()) ||
+ (the_params.streams.is_set() && the_params.streams.value().size() > 0

Would turn into:

if (!the_params.content_id.is_set() && (the_params.streams.is_set() || the_params.streams.value().size() > 0))

Up to you :)

Revision history for this message
Kevin DuBois (kdub) wrote :

> Nit. Couldnt a_surface() take a mir::graphics::BufferProperties? Since we use
> all the same arguments in both. Such as of_buffer_properties(...) or
> something... though either way we have to use those values twice :)
> + auto params = ms::a_surface()
>

Surfaces don't really have pixel_format and usage, these are really just properties of buffers. (although surfaces do have pf/usage fields still from un-cleaned-up cruft).

> Dont see this namespace used in the header.
> +class Session;
This is needed in the remove_content_for() function added to the header

> Shared ptr are defaulted to a nullptr, no need to set it.
> + std::shared_ptr<mf::BufferStream> legacy_stream = nullptr;
>
> // /usr/include/c++/5/tr1/shared_ptr.h:546
> __shared_ptr()
> : _M_ptr(0), _M_refcount() // never throws
> { }

fixed

> This could be a bit simpler, as you have right now:
> !(A || (B && C))
> This could turn into:
> !A && (B || C)
>
> (wanted to do a truth table just to check haha:
> http://paste.ubuntu.com/15635820/)
>
> Not super sure if its *simpler* just reads a bit easier :)
>

Line 6 in the pastebin isn't correct. (the original expression is not computed correctly, the new expression is)

The expression could be reduced I suppose:
!(A || (B && C))
to
!A && !(B && C)
to
!A && (!B || !C)

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Opps youre right! (Dang truth table :).

LGTM

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

The name added_streams is a bit confusing since streams may later be removed as well. How about just calling it 'streams'.
180 + std::unordered_map<SurfaceId, frontend::BufferStreamId> added_streams;
-------------------

We should just call them add_buffer_stream_for() and remove_buffer_stream_for() instead of
170 + void add_content_for(frontend::SurfaceId id, frontend::BufferStreamId);
171 + void remove_content_for(frontend::SurfaceId, frontend::Session&);

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

Hm. Why does the BufferStream Tracker care about the frontend::Session in the remove_content_for method. It seems unbalanced in comparison to the add call. Correct me if I got the wrong picture..

Otherwise it looks fine

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

PASSED: Continuous integration, rev:3445
https://mir-jenkins.ubuntu.com/job/mir-ci/809/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/808
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/845
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/836
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/836
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/817
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/817/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/817
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/817/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/817
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/817/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/817
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/817/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/817
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/817/artifact/output/*zip*/output.zip

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

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

Ok

review: Approve
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

Ok my needs info is gone ..

review: Approve
Revision history for this message
Kevin DuBois (kdub) wrote :

noticed that (for consistency's sake) we should throw when trying to delete a bufferstream that doesnt exist. will fix in this MP before TA.

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

FAILED: Continuous integration, rev:3447
https://mir-jenkins.ubuntu.com/job/mir-ci/816/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/818/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/855
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/846
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/846
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/828
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/828/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/828
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/828/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/828
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/828/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/828
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/828/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/828/console

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

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

I've a feeling this has been seen before, but I can't find the bug...

14:41:46 11: /��BUILDDIR��/mir-0.22.0+xenial846bzr3447/tests/acceptance-tests/test_nested_mir.cpp:1076: Failure
14:41:46 11: Value of: client_config_changed.raised()
14:41:46 11: Actual: false
14:41:46 11: Expected: true
14:41:46 11: [2016-04-12 14:41:46.324381] mirserver: Stopping
14:41:46 11: [2016-04-12 14:41:46.602429] mirserver: Stopping
14:41:46 11: [ FAILED ] NestedServer.when_monitor_plugged_in_client_is_notified_of_new_display_configuration (4453 ms)

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/server_example_canonical_window_manager.cpp'
2--- examples/server_example_canonical_window_manager.cpp 2016-04-05 11:59:12 +0000
3+++ examples/server_example_canonical_window_manager.cpp 2016-04-12 14:23:09 +0000
4@@ -251,13 +251,17 @@
5 return;
6
7 auto format = mir_pixel_format_xrgb_8888;
8- ms::SurfaceCreationParameters params;
9- params.of_size(titlebar_size_for_window(surface->size()))
10+ mir::graphics::BufferProperties properties(titlebar_size_for_window(surface->size()),
11+ format, mir::graphics::BufferUsage::software);
12+ auto stream_id = session->create_buffer_stream(properties);
13+ auto params = ms::a_surface()
14+ .of_size(titlebar_size_for_window(surface->size()))
15 .of_name("decoration")
16 .of_pixel_format(format)
17 .of_buffer_usage(mir::graphics::BufferUsage::software)
18 .of_position(titlebar_position_for_window(surface->top_left()))
19- .of_type(mir_surface_type_gloss);
20+ .of_type(mir_surface_type_gloss)
21+ .with_buffer_stream(stream_id);
22 auto id = build(session, params);
23 auto titlebar = session->surface(id);
24 titlebar->set_alpha(0.9);
25@@ -265,6 +269,7 @@
26 auto& surface_info = tools->info_for(surface);
27 surface_info.titlebar = titlebar;
28 surface_info.titlebar_id = id;
29+ surface_info.titlebar_stream_id = stream_id;
30 surface_info.children.push_back(titlebar);
31
32 SurfaceInfo& titlebar_info =
33@@ -437,6 +442,7 @@
34 if (info.titlebar)
35 {
36 session->destroy_surface(info.titlebar_id);
37+ session->destroy_buffer_stream(info.titlebar_stream_id);
38 tools->forget(info.titlebar);
39 }
40
41
42=== modified file 'examples/server_example_window_management_info.h'
43--- examples/server_example_window_management_info.h 2016-01-29 08:18:22 +0000
44+++ examples/server_example_window_management_info.h 2016-04-12 14:23:09 +0000
45@@ -65,6 +65,7 @@
46 std::vector <std::weak_ptr<scene::Surface>> children;
47 std::shared_ptr <scene::Surface> titlebar;
48 frontend::SurfaceId titlebar_id;
49+ frontend::BufferStreamId titlebar_stream_id;
50 bool is_titlebar = false;
51 geometry::Width min_width;
52 geometry::Height min_height;
53
54=== modified file 'include/server/mir/scene/surface_creation_parameters.h'
55--- include/server/mir/scene/surface_creation_parameters.h 2016-01-29 08:18:22 +0000
56+++ include/server/mir/scene/surface_creation_parameters.h 2016-04-12 14:23:09 +0000
57@@ -101,6 +101,7 @@
58
59 mir::optional_value<std::vector<geometry::Rectangle>> input_shape;
60 mir::optional_value<MirShellChrome> shell_chrome;
61+ mir::optional_value<std::vector<shell::StreamSpecification>> streams;
62 };
63
64 bool operator==(const SurfaceCreationParameters& lhs, const SurfaceCreationParameters& rhs);
65
66=== modified file 'src/client/mir_connection.cpp'
67--- src/client/mir_connection.cpp 2016-03-23 06:39:56 +0000
68+++ src/client/mir_connection.cpp 2016-04-12 14:23:09 +0000
69@@ -172,6 +172,22 @@
70 }
71 }
72
73+ if (spec.streams.is_set())
74+ {
75+ for(auto const& stream : spec.streams.value())
76+ {
77+ auto const new_stream = message.add_stream();
78+ new_stream->set_displacement_x(stream.displacement.dx.as_int());
79+ new_stream->set_displacement_y(stream.displacement.dy.as_int());
80+ new_stream->mutable_id()->set_value(stream.stream_id);
81+ if (stream.size.is_set())
82+ {
83+ new_stream->set_width(stream.size.value().width.as_int());
84+ new_stream->set_height(stream.size.value().height.as_int());
85+ }
86+ }
87+ }
88+
89 return message;
90 }
91
92@@ -400,7 +416,7 @@
93 this, server, &debug, stream, input_platform, spec, *surface_proto, request->wh);
94
95 surface_map->insert(mf::SurfaceId{surface_proto->id().value()}, surf);
96- surface_map->insert(mf::BufferStreamId{surface_proto->id().value()}, stream);
97+ surface_map->insert(mf::BufferStreamId{surface_proto->buffer_stream().id().value()}, stream);
98 }
99
100 callback(surf.get(), context);
101
102=== modified file 'src/protobuf/mir_protobuf.proto'
103--- src/protobuf/mir_protobuf.proto 2016-03-23 06:39:56 +0000
104+++ src/protobuf/mir_protobuf.proto 2016-04-12 14:23:09 +0000
105@@ -39,6 +39,7 @@
106 optional PersistentSurfaceId parent_persistent_id = 21;
107 repeated Rectangle input_shape = 22;
108 optional int32 shell_chrome = 24;
109+ repeated StreamConfiguration stream = 25;
110 }
111
112 message SurfaceAspectRatio
113
114=== modified file 'src/server/frontend/buffer_stream_tracker.cpp'
115--- src/server/frontend/buffer_stream_tracker.cpp 2015-06-17 05:20:42 +0000
116+++ src/server/frontend/buffer_stream_tracker.cpp 2016-04-12 14:23:09 +0000
117@@ -21,6 +21,7 @@
118
119 #include "mir/graphics/buffer.h"
120 #include "mir/graphics/buffer_id.h"
121+#include "mir/frontend/session.h"
122
123 #include <boost/throw_exception.hpp>
124 #include <stdexcept>
125@@ -93,3 +94,26 @@
126 }
127 BOOST_THROW_EXCEPTION(std::logic_error("Buffer is not tracked"));
128 }
129+
130+void mf::BufferStreamTracker::set_default_stream(mf::SurfaceId id, mf::BufferStreamId content)
131+{
132+ std::lock_guard<decltype(mutex)> lock{mutex};
133+ default_streams[id] = content;
134+}
135+
136+mir::optional_value<mf::BufferStreamId> mf::BufferStreamTracker::default_stream(mf::SurfaceId id)
137+{
138+ std::lock_guard<decltype(mutex)> lock{mutex};
139+ auto it = default_streams.find(id);
140+ if (it != default_streams.end())
141+ return it->second;
142+ return {};
143+}
144+
145+void mf::BufferStreamTracker::remove_default_stream(mf::SurfaceId id)
146+{
147+ std::lock_guard<decltype(mutex)> lock{mutex};
148+ auto it = default_streams.find(id);
149+ if (it != default_streams.end())
150+ default_streams.erase(it);
151+}
152
153=== modified file 'src/server/frontend/buffer_stream_tracker.h'
154--- src/server/frontend/buffer_stream_tracker.h 2015-06-17 05:20:42 +0000
155+++ src/server/frontend/buffer_stream_tracker.h 2016-04-12 14:23:09 +0000
156@@ -19,8 +19,10 @@
157 #ifndef MIR_FRONTEND_BUFFER_STREAM_TRACKER_H_
158 #define MIR_FRONTEND_BUFFER_STREAM_TRACKER_H_
159
160+#include "mir/frontend/surface_id.h"
161 #include "mir/frontend/buffer_stream_id.h"
162 #include "mir/graphics/buffer_id.h"
163+#include "mir/optional_value.h"
164
165 #include <unordered_map>
166 #include <memory>
167@@ -56,6 +58,10 @@
168 /* Access the buffer resource that the id corresponds to. */
169 graphics::Buffer* buffer_from(graphics::BufferID) const;
170
171+ void set_default_stream(frontend::SurfaceId id, frontend::BufferStreamId);
172+ optional_value<BufferStreamId> default_stream(SurfaceId id);
173+ void remove_default_stream(frontend::SurfaceId);
174+
175 private:
176 size_t const client_cache_size;
177 std::unordered_map<BufferStreamId, std::shared_ptr<ClientBufferTracker>> client_buffer_tracker;
178@@ -67,6 +73,7 @@
179 private:
180 mutable std::mutex mutex;
181 std::unordered_map<BufferStreamId, graphics::Buffer*> client_buffer_resource;
182+ std::unordered_map<SurfaceId, frontend::BufferStreamId> default_streams;
183 };
184
185 }
186
187=== modified file 'src/server/frontend/session_mediator.cpp'
188--- src/server/frontend/session_mediator.cpp 2016-04-05 03:47:49 +0000
189+++ src/server/frontend/session_mediator.cpp 2016-04-12 14:23:09 +0000
190@@ -286,6 +286,40 @@
191
192 #undef COPY_IF_SET
193
194+ mf::BufferStreamId buffer_stream_id;
195+ std::shared_ptr<mf::BufferStream> legacy_stream = nullptr;
196+ if (request->stream_size() > 0)
197+ {
198+ std::vector<msh::StreamSpecification> stream_spec;
199+ for (auto& stream : request->stream())
200+ {
201+ if (stream.has_width() && stream.has_height())
202+ {
203+ stream_spec.emplace_back(
204+ msh::StreamSpecification{
205+ mf::BufferStreamId{stream.id().value()},
206+ geom::Displacement{stream.displacement_x(), stream.displacement_y()},
207+ geom::Size{stream.width(), stream.height()}});
208+ }
209+ else
210+ {
211+ stream_spec.emplace_back(
212+ msh::StreamSpecification{
213+ mf::BufferStreamId{stream.id().value()},
214+ geom::Displacement{stream.displacement_x(), stream.displacement_y()},
215+ {}});
216+ }
217+ }
218+ params.streams = std::move(stream_spec);
219+ }
220+ else
221+ {
222+ buffer_stream_id = session->create_buffer_stream(
223+ {params.size, params.pixel_format, params.buffer_usage});
224+ legacy_stream = session->get_buffer_stream(buffer_stream_id);
225+ params.content_id = buffer_stream_id;
226+ }
227+
228 if (request->has_min_aspect())
229 params.min_aspect = { request->min_aspect().width(), request->min_aspect().height()};
230
231@@ -298,10 +332,9 @@
232 std::shared_ptr<mf::EventSink> sink = sink_factory->create_sink(buffering_sender);
233
234 auto const surf_id = shell->create_surface(session, params, sink);
235- auto stream_id = mf::BufferStreamId(surf_id.as_value());
236
237 auto surface = session->get_surface(surf_id);
238- auto stream = session->get_buffer_stream(stream_id);
239+ auto stream = session->get_buffer_stream(buffer_stream_id);
240 auto const& client_size = surface->client_size();
241 response->mutable_id()->set_value(surf_id.as_value());
242 response->set_width(client_size.width.as_uint32_t());
243@@ -326,21 +359,29 @@
244 setting->set_ivalue(shell->get_surface_attribute(session, surf_id, static_cast<MirSurfaceAttrib>(i)));
245 }
246
247- advance_buffer(stream_id, *stream, buffer_stream_tracker.last_buffer(stream_id),
248- [this, buffering_sender, surf_id, response, done, session]
249- (graphics::Buffer* client_buffer, graphics::BufferIpcMsgType msg_type)
250- {
251- response->mutable_buffer_stream()->mutable_id()->set_value(surf_id.as_value());
252- if (client_buffer)
253- pack_protobuf_buffer(*response->mutable_buffer_stream()->mutable_buffer(), client_buffer, msg_type);
254-
255-
256- // Send the create_surface reply first...
257- done->Run();
258-
259- // ...then uncork the message sender, sending all buffered surface events.
260- buffering_sender->uncork();
261- });
262+ if (legacy_stream)
263+ {
264+ buffer_stream_tracker.set_default_stream(surf_id, buffer_stream_id);
265+ response->mutable_buffer_stream()->mutable_id()->set_value(buffer_stream_id.as_value());
266+ advance_buffer(buffer_stream_id, *legacy_stream, buffer_stream_tracker.last_buffer(buffer_stream_id),
267+ [this, buffering_sender, response, done, session]
268+ (graphics::Buffer* client_buffer, graphics::BufferIpcMsgType msg_type)
269+ {
270+ if (client_buffer)
271+ pack_protobuf_buffer(*response->mutable_buffer_stream()->mutable_buffer(), client_buffer, msg_type);
272+
273+ // Send the create_surface reply first...
274+ done->Run();
275+
276+ // ...then uncork the message sender, sending all buffered surface events.
277+ buffering_sender->uncork();
278+ });
279+ }
280+ else
281+ {
282+ done->Run();
283+ buffering_sender->uncork();
284+ }
285 }
286
287 void mf::SessionMediator::exchange_buffer(
288@@ -469,7 +510,14 @@
289 auto const id = SurfaceId(request->value());
290
291 shell->destroy_surface(session, id);
292- buffer_stream_tracker.remove_buffer_stream(BufferStreamId(request->value()));
293+
294+ auto default_stream = buffer_stream_tracker.default_stream(id);
295+ if (default_stream.is_set())
296+ {
297+ session->destroy_buffer_stream(default_stream.value());
298+ buffer_stream_tracker.remove_buffer_stream(default_stream.value());
299+ buffer_stream_tracker.remove_default_stream(id);
300+ }
301
302 // TODO: We rely on this sending responses synchronously.
303 done->Run();
304
305=== modified file 'src/server/scene/application_session.cpp'
306--- src/server/scene/application_session.cpp 2016-04-06 08:44:01 +0000
307+++ src/server/scene/application_session.cpp 2016-04-12 14:23:09 +0000
308@@ -90,27 +90,31 @@
309 std::shared_ptr<mf::EventSink> const& surface_sink)
310 {
311 auto const id = next_id();
312- mf::BufferStreamId const stream_id{the_params.content_id.is_set() ?
313- the_params.content_id.value().as_value() : id.as_value()};
314+
315+ //TODO: we take either the content_id or the first streams content for now.
316+ // Once the surface factory interface takes more than one stream,
317+ // we can take all the streams as content.
318+ if (!((the_params.content_id.is_set()) ||
319+ (the_params.streams.is_set() && the_params.streams.value().size() > 0)))
320+ {
321+ BOOST_THROW_EXCEPTION(std::logic_error("surface must have content"));
322+ }
323
324 auto params = the_params;
325
326+ mf::BufferStreamId stream_id;
327+ if (params.content_id.is_set())
328+ stream_id = params.content_id.value();
329+ else
330+ stream_id = params.streams.value()[0].stream_id;
331+
332 if (params.parent_id.is_set())
333 params.parent = checked_find(the_params.parent_id.value())->second;
334
335- std::shared_ptr<compositor::BufferStream> buffer_stream;
336- if (params.content_id.is_set())
337- {
338- buffer_stream = checked_find(params.content_id.value())->second;
339- }
340- else
341- {
342- mg::BufferProperties buffer_properties{params.size,
343- params.pixel_format,
344- params.buffer_usage};
345- buffer_stream = buffer_stream_factory->create_buffer_stream(
346- stream_id, surface_sink, buffer_properties);
347- }
348+ auto buffer_stream = checked_find(params.content_id.value())->second;
349+ if (params.size != buffer_stream->stream_size())
350+ buffer_stream->resize(params.size);
351+
352 auto surface = surface_factory->create_surface(buffer_stream, params);
353 surface_stack->add_surface(surface, params.input_mode);
354
355@@ -133,7 +137,7 @@
356 {
357 std::unique_lock<std::mutex> lock(surfaces_and_streams_mutex);
358 surfaces[id] = surface;
359- streams[stream_id] = buffer_stream;
360+ default_content_map[id] = stream_id;
361 }
362
363 observer->moved_to(surface->top_left());
364@@ -154,7 +158,7 @@
365 {
366 auto p = streams.find(id);
367 if (p == streams.end())
368- BOOST_THROW_EXCEPTION(std::runtime_error("Invalid SurfaceId"));
369+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid BufferStreamId"));
370 return p;
371 }
372
373@@ -220,7 +224,7 @@
374 {
375 if (default_surface() == surface_it.second)
376 {
377- auto id = mf::BufferStreamId(surface_it.first.as_value());
378+ auto id = default_content_map[surface_it.first];
379 snapshot_strategy->take_snapshot_of(checked_find(id)->second, snapshot_taken);
380 return;
381 }
382@@ -360,7 +364,12 @@
383 void ms::ApplicationSession::destroy_buffer_stream(mf::BufferStreamId id)
384 {
385 std::unique_lock<std::mutex> lock(surfaces_and_streams_mutex);
386- streams.erase(checked_find(id));
387+ auto stream_it = streams.find(mir::frontend::BufferStreamId(id.as_value()));
388+ if (stream_it == streams.end())
389+ BOOST_THROW_EXCEPTION(std::runtime_error("cannot destroy stream: Invalid BufferStreamId"));
390+
391+ stream_it->second->drop_outstanding_requests();
392+ streams.erase(stream_it);
393 }
394
395 void ms::ApplicationSession::configure_streams(
396@@ -391,17 +400,12 @@
397 void ms::ApplicationSession::destroy_surface(std::unique_lock<std::mutex>& lock, Surfaces::const_iterator in_surfaces)
398 {
399 auto const surface = in_surfaces->second;
400- auto const id = in_surfaces->first;
401-
402+ auto it = default_content_map.find(in_surfaces->first);
403 session_listener->destroying_surface(*this, surface);
404 surfaces.erase(in_surfaces);
405
406- auto stream_it = streams.find(mir::frontend::BufferStreamId(id.as_value()));
407- if (stream_it != streams.end())
408- {
409- stream_it->second->drop_outstanding_requests();
410- streams.erase(stream_it);
411- }
412+ if (it != default_content_map.end())
413+ default_content_map.erase(it);
414
415 lock.unlock();
416
417
418=== modified file 'src/server/scene/application_session.h'
419--- src/server/scene/application_session.h 2016-04-06 08:44:01 +0000
420+++ src/server/scene/application_session.h 2016-04-12 14:23:09 +0000
421@@ -126,6 +126,8 @@
422 Surfaces surfaces;
423 Streams streams;
424
425+ std::map<frontend::SurfaceId, frontend::BufferStreamId> default_content_map;
426+
427 void destroy_surface(std::unique_lock<std::mutex>& lock, Surfaces::const_iterator in_surfaces);
428 };
429
430
431=== modified file 'tests/integration-tests/session_management.cpp'
432--- tests/integration-tests/session_management.cpp 2016-01-29 08:18:22 +0000
433+++ tests/integration-tests/session_management.cpp 2016-04-12 14:23:09 +0000
434@@ -95,8 +95,6 @@
435 std::shared_ptr<mf::EventSink> const event_sink = std::make_shared<mtd::NullEventSink>();
436 std::shared_ptr<mf::Shell> const session_manager = builder.the_frontend_shell();
437 std::shared_ptr<TestSurfaceStack> const& test_surface_stack = builder.test_surface_stack;
438- ms::SurfaceCreationParameters const params = ms::SurfaceCreationParameters().of_size(100,100).of_type(mir_surface_type_normal);
439-
440 void SetUp()
441 {
442 ASSERT_THAT(test_surface_stack, Ne(nullptr));
443@@ -117,6 +115,13 @@
444 {
445 auto const session = session_manager->open_session(0, __PRETTY_FUNCTION__, event_sink);
446
447+ mir::graphics::BufferProperties properties(
448+ mir::geometry::Size{1,1}, mir_pixel_format_abgr_8888, mir::graphics::BufferUsage::software);
449+ ms::SurfaceCreationParameters const params = ms::SurfaceCreationParameters()
450+ .of_size(100,100)
451+ .of_type(mir_surface_type_normal)
452+ .with_buffer_stream(session->create_buffer_stream(properties));
453+
454 EXPECT_CALL(*test_surface_stack, add_surface(_,_)).Times(1);
455 session_manager->create_surface(session, params, event_sink);
456 }
457
458=== modified file 'tests/integration-tests/test_session.cpp'
459--- tests/integration-tests/test_session.cpp 2016-01-29 08:18:22 +0000
460+++ tests/integration-tests/test_session.cpp 2016-04-12 14:23:09 +0000
461@@ -126,7 +126,11 @@
462 mtd::StubDisplayConfig{},
463 std::make_shared<mtd::NullEventSink>()
464 };
465- session.create_surface(ms::a_surface(), std::make_shared<mtd::NullEventSink>());
466+
467+ mg::BufferProperties properties(geom::Size{1,1}, mir_pixel_format_abgr_8888, mg::BufferUsage::software);
468+ session.create_surface(
469+ ms::a_surface().with_buffer_stream(session.create_buffer_stream(properties)),
470+ std::make_shared<mtd::NullEventSink>());
471
472 auto compositor = conf.the_compositor();
473
474
475=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
476--- tests/unit-tests/frontend/test_session_mediator.cpp 2016-04-05 03:47:49 +0000
477+++ tests/unit-tests/frontend/test_session_mediator.cpp 2016-04-12 14:23:09 +0000
478@@ -111,11 +111,6 @@
479 class StubbedSession : public mtd::StubSession
480 {
481 public:
482- StubbedSession() :
483- last_surface_id{0}
484- {
485- }
486-
487 std::shared_ptr<mf::Surface> get_surface(mf::SurfaceId surface) const
488 {
489 if (mock_surfaces.find(surface) == mock_surfaces.end())
490@@ -126,7 +121,7 @@
491 std::shared_ptr<mf::BufferStream> get_buffer_stream(mf::BufferStreamId stream) const override
492 {
493 if (mock_streams.find(stream) == mock_streams.end())
494- BOOST_THROW_EXCEPTION(std::logic_error("Invalid SurfaceId"));
495+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid StreamId"));
496 return mock_streams.at(stream);
497 }
498
499@@ -137,43 +132,37 @@
500 return mock_surfaces.at(id);
501 }
502
503- std::shared_ptr<mtd::MockBufferStream> mock_primary_stream_at(mf::SurfaceId id)
504+ std::shared_ptr<mtd::MockBufferStream> mock_stream_at(mf::BufferStreamId id)
505 {
506- if (mock_surfaces.end() == mock_surfaces.find(id))
507- create_mock_surface(id);
508- return mock_streams.at(mf::BufferStreamId(id.as_value()));
509+ if (mock_streams.end() == mock_streams.find(id))
510+ return create_mock_stream(id);
511+ return mock_streams.at(id);
512 }
513
514 std::shared_ptr<mtd::MockFrontendSurface> create_mock_surface(mf::SurfaceId id)
515 {
516 using namespace testing;
517+ mg::BufferProperties properties;
518+ create_buffer_stream(properties);
519 auto surface = std::make_shared<testing::NiceMock<mtd::MockFrontendSurface>>(testing_client_input_fd);
520- auto stream = std::make_shared<testing::NiceMock<mtd::MockBufferStream>>();
521+ mock_surfaces[id] = surface;
522+ return surface;
523+ }
524
525+ std::shared_ptr<mtd::MockBufferStream> create_mock_stream(mf::BufferStreamId id)
526+ {
527+ mock_streams[id] = std::make_shared<testing::NiceMock<mtd::MockBufferStream>>();
528 auto buffer1 = std::make_shared<mtd::StubBuffer>();
529 auto buffer2 = std::make_shared<mtd::StubBuffer>();
530- ON_CALL(*stream, swap_buffers(testing::_,testing::_))
531+ ON_CALL(*mock_streams[id], swap_buffers(testing::_,testing::_))
532 .WillByDefault(testing::Invoke(
533 [buffer1, buffer2](mg::Buffer* b, std::function<void(mg::Buffer* new_buffer)> complete)
534 {
535 if ((!b) || (b == buffer1.get()))
536 complete(buffer2.get());
537 if (b == buffer2.get())
538- complete(buffer1.get());
539+ complete(buffer1.get());
540 }));
541-
542- ON_CALL(*surface, primary_buffer_stream())
543- .WillByDefault(Return(stream));
544-
545-
546- mock_surfaces[id] = surface;
547- mock_streams[mf::BufferStreamId(id.as_value())] = stream;
548- return surface;
549- }
550-
551- std::shared_ptr<mtd::MockBufferStream> create_mock_stream(mf::BufferStreamId id)
552- {
553- mock_streams[id] = std::make_shared<testing::NiceMock<mtd::MockBufferStream>>();
554 return mock_streams[id];
555 }
556
557@@ -190,10 +179,10 @@
558
559 mf::BufferStreamId create_buffer_stream(mg::BufferProperties const&)
560 {
561- mf::BufferStreamId id{last_surface_id};
562+ mf::BufferStreamId id{last_stream_id};
563 if (mock_streams.end() == mock_streams.find(id))
564 create_mock_stream(id);
565- last_surface_id++;
566+ last_stream_id++;
567 return id;
568 }
569
570@@ -205,7 +194,8 @@
571 std::map<mf::BufferStreamId, std::shared_ptr<mtd::MockBufferStream>> mock_streams;
572 std::map<mf::SurfaceId, std::shared_ptr<mtd::MockFrontendSurface>> mock_surfaces;
573 static int const testing_client_input_fd;
574- int last_surface_id;
575+ int last_surface_id = 0;
576+ int last_stream_id = 0;
577 };
578
579 int const StubbedSession::testing_client_input_fd{11};
580@@ -298,6 +288,7 @@
581 mp::Buffer buffer_response;
582 mp::BufferRequest buffer_request;
583 };
584+
585 }
586
587 TEST_F(SessionMediator, disconnect_releases_session)
588@@ -388,10 +379,6 @@
589 }, std::logic_error);
590
591 EXPECT_THROW({
592- mediator.exchange_buffer(&buffer_request, &buffer_response, null_callback.get());
593- }, std::logic_error);
594-
595- EXPECT_THROW({
596 mediator.release_surface(&surface_id_request, nullptr, null_callback.get());
597 }, std::logic_error);
598
599@@ -510,7 +497,7 @@
600 mp::SurfaceParameters surface_request;
601 mp::Surface surface_response;
602
603- auto stream1 = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
604+ auto stream1 = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
605 ON_CALL(*stream1, swap_buffers(_,_))
606 .WillByDefault(InvokeArgument<1>(&buffer));
607
608@@ -653,7 +640,7 @@
609 TEST_F(SessionMediator, exchange_buffer)
610 {
611 using namespace testing;
612- auto const& mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
613+ auto mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
614 mp::Buffer exchanged_buffer;
615 mtd::StubBuffer stub_buffer1;
616 mtd::StubBuffer stub_buffer2;
617@@ -682,10 +669,10 @@
618 {
619 using namespace testing;
620 mp::Buffer exchanged_buffer;
621- mf::SurfaceId surf_id{0};
622+ mf::BufferStreamId stream_id{0};
623 mtd::StubBuffer buffer1;
624 mtd::StubBuffer buffer2;
625- auto stream = stubbed_session->mock_primary_stream_at(surf_id);
626+ auto stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
627 ON_CALL(*stream, swap_buffers(nullptr,_))
628 .WillByDefault(InvokeArgument<1>(&buffer2));
629 ON_CALL(*stream, swap_buffers(&buffer1,_))
630@@ -732,7 +719,7 @@
631 TEST_F(SessionMediator, exchange_buffer_throws_if_client_submits_bad_request)
632 {
633 using namespace testing;
634- auto const& mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
635+ auto mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
636 mp::Buffer exchanged_buffer;
637 mtd::StubBuffer stub_buffer1;
638 mtd::StubBuffer stub_buffer2;
639@@ -765,8 +752,8 @@
640 mp::SurfaceParameters surface_request;
641 mp::BufferRequest req1;
642 mp::BufferRequest req2;
643- auto const& mock_stream1 = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
644- auto const& mock_stream2 = stubbed_session->mock_primary_stream_at(mf::SurfaceId{1});
645+ auto mock_stream1 = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
646+ auto mock_stream2 = stubbed_session->mock_stream_at(mf::BufferStreamId{2});
647 Sequence seq;
648 EXPECT_CALL(*mock_stream1, swap_buffers(_,_))
649 .InSequence(seq);
650@@ -780,10 +767,10 @@
651 mediator.connect(&connect_parameters, &connection, null_callback.get());
652
653 mediator.create_surface(&surface_request, &surface_response, null_callback.get());
654- req1.mutable_id()->set_value(surface_response.id().value());
655+ req1.mutable_id()->set_value(surface_response.buffer_stream().id().value());
656 *req1.mutable_buffer() = surface_response.buffer_stream().buffer();
657 mediator.create_surface(&surface_request, &surface_response, null_callback.get());
658- req2.mutable_id()->set_value(surface_response.id().value());
659+ req2.mutable_id()->set_value(surface_response.buffer_stream().id().value());
660 *req2.mutable_buffer() = surface_response.buffer_stream().buffer();
661 mediator.exchange_buffer(&req2, &buffer_response, null_callback.get());
662 mediator.exchange_buffer(&req1, &buffer_response, null_callback.get());
663@@ -840,7 +827,7 @@
664 TEST_F(SessionMediator, completes_exchange_buffer_when_completion_is_invoked_asynchronously_from_thread_that_initiated_exchange)
665 {
666 using namespace testing;
667- auto const& mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
668+ auto const& mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
669 mtd::StubBuffer stub_buffer1;
670 mtd::StubBuffer stub_buffer2;
671 std::function<void(mg::Buffer*)> completion_func;
672@@ -954,7 +941,7 @@
673 mediator.connect(&connect_parameters, &connection, null_callback.get());
674 mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
675
676- auto mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
677+ auto mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
678 request.mutable_id()->set_value(surface_response.id().value());
679 request.mutable_buffer()->set_buffer_id(buffer1->id().as_value());
680
681@@ -989,7 +976,7 @@
682 mediator.connect(&connect_parameters, &connection, null_callback.get());
683 mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
684
685- auto mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
686+ auto mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
687 EXPECT_CALL(*mock_stream, allocate_buffer(properties))
688 .Times(num_requests)
689 .WillRepeatedly(Return(mg::BufferID{}));
690@@ -1016,7 +1003,7 @@
691 mediator.connect(&connect_parameters, &connection, null_callback.get());
692 mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
693
694- auto mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
695+ auto mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
696 EXPECT_CALL(*mock_stream, remove_buffer(mg::BufferID{buffer_id}))
697 .Times(num_requests);
698
699@@ -1026,7 +1013,7 @@
700 TEST_F(SessionMediator, doesnt_mind_swap_buffers_returning_nullptr_in_submit)
701 {
702 using namespace testing;
703- auto mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0});
704+ auto mock_stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
705 ON_CALL(*mock_stream, swap_buffers(_,_))
706 .WillByDefault(InvokeArgument<1>(nullptr));
707 auto buffer1 = std::make_shared<mtd::StubBuffer>();
708@@ -1062,10 +1049,9 @@
709 TEST_F(SessionMediator, doesnt_mind_swap_buffers_returning_nullptr_in_create)
710 {
711 using namespace testing;
712- mf::SurfaceId surf_id{0};
713 mtd::StubBuffer buffer;
714
715- auto stream = stubbed_session->mock_primary_stream_at(surf_id);
716+ auto stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
717 ON_CALL(*stream, swap_buffers(_,_))
718 .WillByDefault(InvokeArgument<1>(nullptr));
719
720@@ -1081,10 +1067,9 @@
721 TEST_F(SessionMediator, doesnt_mind_swap_buffers_returning_nullptr_in_bstream_create)
722 {
723 using namespace testing;
724- mf::SurfaceId surf_id{0};
725 mtd::StubBuffer buffer;
726
727- auto stream = stubbed_session->mock_primary_stream_at(surf_id);
728+ auto stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
729 ON_CALL(*stream, swap_buffers(_,_))
730 .WillByDefault(InvokeArgument<1>(nullptr));
731
732@@ -1100,20 +1085,20 @@
733 TEST_F(SessionMediator, configures_swap_intervals_on_streams)
734 {
735 using namespace testing;
736- mf::SurfaceId surf_id{0};
737+ mf::BufferStreamId stream_id{0};
738 mp::StreamConfiguration request;
739 mp::Void response;
740
741 auto interval = 0u;
742 mtd::StubBuffer buffer;
743
744- auto stream = stubbed_session->mock_primary_stream_at(surf_id);
745+ auto stream = stubbed_session->mock_stream_at(stream_id);
746 EXPECT_CALL(*stream, allow_framedropping(true));
747
748 mediator.connect(&connect_parameters, &connection, null_callback.get());
749 mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
750
751- request.mutable_id()->set_value(surf_id.as_value());
752+ request.mutable_id()->set_value(stream_id.as_value());
753 request.set_swapinterval(interval);
754 mediator.configure_buffer_stream(&request, &response, null_callback.get());
755 }
756@@ -1209,10 +1194,9 @@
757 TEST_F(SessionMediator, doesnt_inadventently_set_buffer_field_when_theres_no_buffer)
758 {
759 mp::Void null;
760- mf::SurfaceId surf_id{0};
761 mp::BufferStreamParameters stream_request;
762 mp::BufferStream stream_response;
763- auto stream = stubbed_session->mock_primary_stream_at(surf_id);
764+ auto stream = stubbed_session->mock_stream_at(mf::BufferStreamId{0});
765 ON_CALL(*stream, swap_buffers(nullptr,testing::_))
766 .WillByDefault(testing::InvokeArgument<1>(nullptr));
767 mediator.connect(&connect_parameters, &connection, null_callback.get());
768
769=== modified file 'tests/unit-tests/scene/test_abstract_shell.cpp'
770--- tests/unit-tests/scene/test_abstract_shell.cpp 2016-01-29 08:18:22 +0000
771+++ tests/unit-tests/scene/test_abstract_shell.cpp 2016-04-12 14:23:09 +0000
772@@ -145,6 +145,7 @@
773
774 std::chrono::nanoseconds const event_timestamp = std::chrono::nanoseconds(0);
775 std::vector<uint8_t> const cookie;
776+ mg::BufferProperties properties { geom::Size{1,1}, mir_pixel_format_abgr_8888, mg::BufferUsage::software};
777 };
778 }
779
780@@ -197,9 +198,12 @@
781 WillOnce(Return(mt::fake_shared(surface3)));
782
783 auto const session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
784- auto const surface_id1 = shell.create_surface(session, ms::a_surface(), nullptr);
785- auto const surface_id2 = shell.create_surface(session, ms::a_surface(), nullptr);
786- auto const surface_id3 = shell.create_surface(session, ms::a_surface(), nullptr);
787+ auto const surface_id1 = shell.create_surface(session,
788+ ms::a_surface().with_buffer_stream(session->create_buffer_stream(properties)), nullptr);
789+ auto const surface_id2 = shell.create_surface(session,
790+ ms::a_surface().with_buffer_stream(session->create_buffer_stream(properties)), nullptr);
791+ auto const surface_id3 = shell.create_surface(session,
792+ ms::a_surface().with_buffer_stream(session->create_buffer_stream(properties)), nullptr);
793
794 session->destroy_surface(surface_id2);
795
796@@ -217,8 +221,8 @@
797 std::shared_ptr<ms::Session> session =
798 shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
799
800- auto params = ms::a_surface();
801-
802+ auto params = ms::a_surface()
803+ .with_buffer_stream(session->create_buffer_stream(properties));
804 EXPECT_CALL(*wm, add_surface(session, Ref(params), _));
805
806 shell.create_surface(session, params, nullptr);
807@@ -229,7 +233,8 @@
808 std::shared_ptr<ms::Session> const session =
809 shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
810
811- auto params = ms::a_surface();
812+ auto params = ms::a_surface()
813+ .with_buffer_stream(session->create_buffer_stream(properties));
814 auto placed_params = params;
815 placed_params.size.width = geom::Width{100};
816
817@@ -246,9 +251,10 @@
818
819 TEST_F(AbstractShell, destroy_surface_removes_surface_from_window_manager)
820 {
821- auto const params = ms::a_surface();
822 std::shared_ptr<ms::Session> const session =
823 shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
824+ auto const params = ms::a_surface()
825+ .with_buffer_stream(session->create_buffer_stream(properties));
826
827 auto const surface_id = shell.create_surface(session, params, nullptr);
828 auto const surface = session->surface(surface_id);
829@@ -357,7 +363,9 @@
830 std::shared_ptr<ms::Session> const session =
831 shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
832
833- auto const surface_id = shell.create_surface(session, ms::a_surface(), nullptr);
834+ auto const params = ms::a_surface()
835+ .with_buffer_stream(session->create_buffer_stream(properties));
836+ auto const surface_id = shell.create_surface(session, params, nullptr);
837 auto const surface = session->surface(surface_id);
838
839 MirSurfaceState const state{mir_surface_state_fullscreen};
840@@ -392,8 +400,12 @@
841 msh::FocusController& focus_controller = shell;
842 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
843 auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
844- shell.create_surface(session, ms::a_surface(), nullptr);
845- shell.create_surface(session1, ms::a_surface(), nullptr);
846+ auto const params = ms::a_surface()
847+ .with_buffer_stream(session->create_buffer_stream(properties));
848+ auto const params2 = ms::a_surface()
849+ .with_buffer_stream(session1->create_buffer_stream(properties));
850+ shell.create_surface(session, params, nullptr);
851+ shell.create_surface(session1, params2, nullptr);
852
853 focus_controller.set_focus_to(session, {});
854
855@@ -409,8 +421,12 @@
856 {
857 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
858 auto session1 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
859- shell.create_surface(session, ms::a_surface(), nullptr);
860- shell.create_surface(session1, ms::a_surface(), nullptr);
861+ auto const params = ms::a_surface()
862+ .with_buffer_stream(session->create_buffer_stream(properties));
863+ auto const params2 = ms::a_surface()
864+ .with_buffer_stream(session1->create_buffer_stream(properties));
865+ shell.create_surface(session, params, nullptr);
866+ shell.create_surface(session1, params2, nullptr);
867
868 EXPECT_CALL(session_container, successor_of(session1)).
869 WillOnce(Return(session));
870@@ -437,10 +453,13 @@
871 EXPECT_CALL(session_container, successor_of(session1)).
872 WillOnce(Return(session0));
873
874-
875- auto const surface0_id = shell.create_surface(session0, ms::a_surface(), nullptr);
876+ auto const params = ms::a_surface()
877+ .with_buffer_stream(session0->create_buffer_stream(properties));
878+ auto const params2 = ms::a_surface()
879+ .with_buffer_stream(session1->create_buffer_stream(properties));
880+ auto const surface0_id = shell.create_surface(session0, params, nullptr);
881 auto const surface0 = session0->surface(surface0_id);
882- auto const surface1_id = shell.create_surface(session1, ms::a_surface(), nullptr);
883+ auto const surface1_id = shell.create_surface(session1, params2, nullptr);
884 auto const surface1 = session1->surface(surface1_id);
885
886 msh::FocusController& focus_controller = shell;
887@@ -477,8 +496,12 @@
888 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
889 auto session1 = shell.open_session(__LINE__, "Surfaceless", std::shared_ptr<mf::EventSink>());
890 auto session2 = shell.open_session(__LINE__, "Bla", std::shared_ptr<mf::EventSink>());
891- auto surface_id = shell.create_surface(session, ms::a_surface(), nullptr);
892- shell.create_surface(session2, ms::a_surface(), nullptr);
893+ auto const params = ms::a_surface()
894+ .with_buffer_stream(session->create_buffer_stream(properties));
895+ auto surface_id = shell.create_surface(session, params, nullptr);
896+ auto const params2 = ms::a_surface()
897+ .with_buffer_stream(session2->create_buffer_stream(properties));
898+ shell.create_surface(session2, params2, nullptr);
899
900 focus_controller.set_focus_to(session, session->surface(surface_id));
901
902@@ -498,7 +521,9 @@
903 msh::FocusController& focus_controller = shell;
904 auto session = shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
905 auto session1 = shell.open_session(__LINE__, "Surfaceless", std::shared_ptr<mf::EventSink>());
906- auto surface_id = shell.create_surface(session, ms::a_surface(), nullptr);
907+ auto creation_params = ms::a_surface()
908+ .with_buffer_stream(session->create_buffer_stream(properties));
909+ auto surface_id = shell.create_surface(session, creation_params, nullptr);
910
911 focus_controller.set_focus_to(session, session->surface(surface_id));
912
913@@ -519,8 +544,8 @@
914 std::shared_ptr<ms::Session> session =
915 shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
916
917- auto creation_params = ms::a_surface();
918-
919+ auto creation_params = ms::a_surface()
920+ .with_buffer_stream(session->create_buffer_stream(properties));
921 auto surface_id = shell.create_surface(session, creation_params, nullptr);
922 auto surface = session->surface(surface_id);
923
924@@ -537,7 +562,8 @@
925 std::shared_ptr<ms::Session> session =
926 shell.open_session(__LINE__, "XPlane", std::shared_ptr<mf::EventSink>());
927
928- auto creation_params = ms::a_surface();
929+ auto creation_params = ms::a_surface()
930+ .with_buffer_stream(session->create_buffer_stream(properties));
931
932 auto surface_id = shell.create_surface(session, creation_params, nullptr);
933 auto surface = session->surface(surface_id);
934
935=== modified file 'tests/unit-tests/scene/test_application_session.cpp'
936--- tests/unit-tests/scene/test_application_session.cpp 2016-04-04 03:30:04 +0000
937+++ tests/unit-tests/scene/test_application_session.cpp 2016-04-12 14:23:09 +0000
938@@ -223,6 +223,7 @@
939 std::shared_ptr<mtd::StubBufferStream> const stub_buffer_stream{std::make_shared<mtd::StubBufferStream>()};
940 pid_t pid;
941 std::string name;
942+ mg::BufferProperties properties { geom::Size{1,1}, mir_pixel_format_abgr_8888, mg::BufferUsage::hardware };
943 };
944
945 struct MockSurfaceFactory : ms::SurfaceFactory
946@@ -246,10 +247,48 @@
947 auto session = make_application_session(
948 mt::fake_shared(surface_stack), mt::fake_shared(mock_surface_factory));
949
950- ms::SurfaceCreationParameters params;
951- auto surf = session->create_surface(params, event_sink);
952-
953- session->destroy_surface(surf);
954+ ms::SurfaceCreationParameters params = ms::a_surface()
955+ .with_buffer_stream(session->create_buffer_stream(properties));
956+ auto surf = session->create_surface(params, event_sink);
957+
958+ session->destroy_surface(surf);
959+}
960+
961+TEST_F(ApplicationSession, attempt_to_destroy_non_existent_stream_throws)
962+{
963+ using namespace ::testing;
964+ NiceMock<MockSurfaceFactory> mock_surface_factory;
965+ NiceMock<mtd::MockSurfaceStack> surface_stack;
966+ auto session = make_application_session(
967+ mt::fake_shared(surface_stack), mt::fake_shared(mock_surface_factory));
968+
969+ mf::BufferStreamId made_up_id{332};
970+ EXPECT_THROW({
971+ session->destroy_buffer_stream(made_up_id);
972+ }, std::runtime_error);
973+}
974+
975+TEST_F(ApplicationSession, can_destroy_buffer_stream_after_destroying_surface)
976+{
977+ using namespace ::testing;
978+
979+ NiceMock<MockSurfaceFactory> mock_surface_factory;
980+ NiceMock<mtd::MockSurfaceStack> surface_stack;
981+ std::shared_ptr<ms::Surface> mock_surface = make_mock_surface();
982+
983+ EXPECT_CALL(mock_surface_factory, create_surface(_,_))
984+ .WillOnce(Return(mock_surface));
985+ EXPECT_CALL(surface_stack, add_surface(mock_surface,_));
986+ auto session = make_application_session(
987+ mt::fake_shared(surface_stack), mt::fake_shared(mock_surface_factory));
988+
989+ auto buffer_stream = session->create_buffer_stream(properties);
990+ ms::SurfaceCreationParameters params = ms::a_surface()
991+ .with_buffer_stream(buffer_stream);
992+ auto surf = session->create_surface(params, event_sink);
993+
994+ session->destroy_surface(surf);
995+ session->destroy_buffer_stream(buffer_stream);
996 }
997
998 TEST_F(ApplicationSession, notifies_listener_of_create_and_destroy_surface)
999@@ -264,7 +303,8 @@
1000
1001 auto session = make_application_session_with_listener(mt::fake_shared(listener));
1002
1003- ms::SurfaceCreationParameters params;
1004+ ms::SurfaceCreationParameters params = ms::a_surface()
1005+ .with_buffer_stream(session->create_buffer_stream(properties));
1006 auto surf = session->create_surface(params, event_sink);
1007
1008 session->destroy_surface(surf);
1009@@ -283,7 +323,8 @@
1010 {
1011 auto session = make_application_session_with_listener(mt::fake_shared(listener));
1012
1013- ms::SurfaceCreationParameters params;
1014+ ms::SurfaceCreationParameters params = ms::a_surface()
1015+ .with_buffer_stream(session->create_buffer_stream(properties));
1016 session->create_surface(params, event_sink);
1017 }
1018 }
1019@@ -320,7 +361,8 @@
1020
1021 auto app_session = make_application_session_with_stubs();
1022
1023- ms::SurfaceCreationParameters params;
1024+ ms::SurfaceCreationParameters params = ms::a_surface()
1025+ .with_buffer_stream(app_session->create_buffer_stream(properties));
1026 auto id1 = app_session->create_surface(params, nullptr);
1027 auto id2 = app_session->create_surface(params, nullptr);
1028 auto id3 = app_session->create_surface(params, nullptr);
1029@@ -341,7 +383,8 @@
1030 TEST_F(ApplicationSession, foreign_surface_has_no_successor)
1031 {
1032 auto session1 = make_application_session_with_stubs();
1033- ms::SurfaceCreationParameters params;
1034+ ms::SurfaceCreationParameters params = ms::a_surface()
1035+ .with_buffer_stream(session1->create_buffer_stream(properties));
1036 auto id1 = session1->create_surface(params, nullptr);
1037 auto surf1 = session1->surface(id1);
1038 auto id2 = session1->create_surface(params, nullptr);
1039@@ -358,7 +401,8 @@
1040 TEST_F(ApplicationSession, surface_after_one_is_self)
1041 {
1042 auto session = make_application_session_with_stubs();
1043- ms::SurfaceCreationParameters params;
1044+ ms::SurfaceCreationParameters params = ms::a_surface()
1045+ .with_buffer_stream(session->create_buffer_stream(properties));
1046 auto id = session->create_surface(params, nullptr);
1047 auto surf = session->surface(id);
1048
1049@@ -371,7 +415,8 @@
1050 {
1051 auto app_session = make_application_session_with_stubs();
1052
1053- ms::SurfaceCreationParameters params;
1054+ ms::SurfaceCreationParameters params = ms::a_surface()
1055+ .with_buffer_stream(app_session->create_buffer_stream(properties));
1056
1057 int const N = 3;
1058 std::shared_ptr<ms::Surface> surf[N];
1059@@ -412,7 +457,8 @@
1060 EXPECT_CALL(*mock_surface, show()).Times(1);
1061 }
1062
1063- ms::SurfaceCreationParameters params;
1064+ ms::SurfaceCreationParameters params = ms::a_surface()
1065+ .with_buffer_stream(app_session->create_buffer_stream(properties));
1066 auto surf = app_session->create_surface(params, event_sink);
1067
1068 app_session->hide();
1069@@ -447,7 +493,9 @@
1070 mtd::StubDisplayConfig{},
1071 event_sink);
1072
1073- auto surface = app_session.create_surface(ms::SurfaceCreationParameters{}, event_sink);
1074+ ms::SurfaceCreationParameters params = ms::a_surface()
1075+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1076+ auto surface = app_session.create_surface(params, event_sink);
1077 app_session.take_snapshot(ms::SnapshotCallback());
1078 app_session.destroy_surface(surface);
1079 }
1080@@ -492,42 +540,13 @@
1081 EXPECT_THAT(app_session.process_id(), Eq(session_pid));
1082 }
1083
1084-TEST_F(ApplicationSession, surface_ids_are_bufferstream_ids)
1085-{
1086- using namespace ::testing;
1087-
1088- NiceMock<MockSurfaceFactory> mock_surface_factory;
1089- NiceMock<MockBufferStreamFactory> mock_bufferstream_factory;
1090- NiceMock<mtd::MockSurfaceStack> surface_stack;
1091- std::shared_ptr<ms::Surface> mock_surface = make_mock_surface();
1092- auto stub_bstream = std::make_shared<mtd::StubBufferStream>();
1093- EXPECT_CALL(mock_bufferstream_factory, create_buffer_stream(_,_,_))
1094- .WillOnce(Return(stub_bstream));
1095- EXPECT_CALL(mock_surface_factory, create_surface(std::shared_ptr<mc::BufferStream>(stub_bstream),_))
1096- .WillOnce(Return(mock_surface));
1097- auto session = make_application_session(
1098- mt::fake_shared(mock_bufferstream_factory),
1099- mt::fake_shared(mock_surface_factory));
1100-
1101- ms::SurfaceCreationParameters params;
1102-
1103- auto id1 = session->create_surface(params, event_sink);
1104- EXPECT_THAT(session->get_buffer_stream(mf::BufferStreamId(id1.as_value())), Eq(stub_bstream));
1105- EXPECT_THAT(session->get_surface(id1), Eq(mock_surface));
1106-
1107- session->destroy_surface(id1);
1108-
1109- EXPECT_THROW({
1110- session->get_buffer_stream(mf::BufferStreamId(id1.as_value()));
1111- }, std::runtime_error);
1112-}
1113-
1114 TEST_F(ApplicationSession, can_destroy_surface_bstream)
1115 {
1116 auto session = make_application_session_with_stubs();
1117- ms::SurfaceCreationParameters params;
1118+ mf::BufferStreamId stream_id = session->create_buffer_stream(properties);
1119+ ms::SurfaceCreationParameters params = ms::a_surface()
1120+ .with_buffer_stream(stream_id);
1121 auto id = session->create_surface(params, event_sink);
1122- mf::BufferStreamId stream_id(id.as_value());
1123 session->destroy_buffer_stream(stream_id);
1124 EXPECT_THROW({
1125 session->get_buffer_stream(stream_id);
1126@@ -565,11 +584,8 @@
1127 auto session = make_application_session(
1128 mt::fake_shared(mock_bufferstream_factory),
1129 mt::fake_shared(mock_surface_factory));
1130- auto stream_id0 = mf::BufferStreamId(
1131- session->create_surface(
1132- ms::a_surface().of_position({1,1}),
1133- event_sink).as_value());
1134
1135+ auto stream_id0 = session->create_buffer_stream(stream_properties);
1136 auto stream_id1 = session->create_buffer_stream(stream_properties);
1137 auto stream_id2 = session->create_buffer_stream(stream_properties);
1138
1139@@ -578,6 +594,10 @@
1140 {streams[0], geom::Displacement{-1,1}, {}},
1141 {streams[1], geom::Displacement{0,2}, {}}
1142 };
1143+
1144+ session->create_surface(
1145+ ms::a_surface().with_buffer_stream(stream_id0), event_sink);
1146+
1147 EXPECT_CALL(*mock_surface, set_streams(Pointwise(StreamEq(), info)));
1148 session->configure_streams(*mock_surface, {
1149 {stream_id2, geom::Displacement{0,3}, {}},
1150@@ -884,7 +904,8 @@
1151 app_session.send_display_config(config);
1152
1153 ms::SurfaceCreationParameters params = ms::SurfaceCreationParameters{}
1154- .of_size({100, 100});
1155+ .of_size({100, 100})
1156+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1157 auto surf_id = app_session.create_surface(params, sender);
1158 auto surface = app_session.surface(surf_id);
1159
1160@@ -909,7 +930,8 @@
1161 }));
1162
1163 ms::SurfaceCreationParameters params = ms::SurfaceCreationParameters{}
1164- .of_size({100, 100});
1165+ .of_size({100, 100})
1166+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1167
1168 mf::SurfaceId ids[2];
1169 std::shared_ptr<ms::Surface> surfaces[2];
1170@@ -962,7 +984,8 @@
1171 }));
1172
1173 ms::SurfaceCreationParameters params = ms::SurfaceCreationParameters{}
1174- .of_size({100, 100});
1175+ .of_size({100, 100})
1176+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1177
1178 auto id = app_session.create_surface(params, sender);
1179 auto surface = app_session.surface(id);
1180@@ -1019,7 +1042,8 @@
1181 app_session.send_display_config(config);
1182
1183 ms::SurfaceCreationParameters params = ms::SurfaceCreationParameters{}
1184- .of_size({640, 480});
1185+ .of_size({640, 480})
1186+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1187
1188 auto id = app_session.create_surface(params, sender);
1189 auto surface = app_session.surface(id);
1190@@ -1076,7 +1100,8 @@
1191 app_session.send_display_config(config);
1192
1193 ms::SurfaceCreationParameters params = ms::SurfaceCreationParameters{}
1194- .of_size({100, 100});
1195+ .of_size({100, 100})
1196+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1197
1198 auto id = app_session.create_surface(params, sender);
1199 auto surface = app_session.surface(id);
1200@@ -1138,7 +1163,8 @@
1201 app_session.send_display_config(config);
1202
1203 ms::SurfaceCreationParameters params = ms::SurfaceCreationParameters{}
1204- .of_size({100, 100});
1205+ .of_size({100, 100})
1206+ .with_buffer_stream(app_session.create_buffer_stream(properties));
1207
1208 auto id = app_session.create_surface(params, sender);
1209 auto surface = app_session.surface(id);
1210
1211=== modified file 'tests/unit-tests/scene/test_session_manager.cpp'
1212--- tests/unit-tests/scene/test_session_manager.cpp 2016-01-29 08:18:22 +0000
1213+++ tests/unit-tests/scene/test_session_manager.cpp 2016-04-12 14:23:09 +0000
1214@@ -129,9 +129,13 @@
1215 EXPECT_CALL(container, insert_session(_)).Times(1);
1216 EXPECT_CALL(container, remove_session(_)).Times(1);
1217
1218+ mg::BufferProperties properties {
1219+ geom::Size{1,1}, mir_pixel_format_abgr_8888, mg::BufferUsage::software };
1220 auto session = session_manager.open_session(__LINE__, "Visual Basic Studio", mt::fake_shared(event_sink));
1221 session->create_surface(
1222- ms::a_surface().of_size(geom::Size{geom::Width{1024}, geom::Height{768}}),
1223+ ms::a_surface()
1224+ .of_size(geom::Size{geom::Width{1024}, geom::Height{768}})
1225+ .with_buffer_stream(session->create_buffer_stream(properties)),
1226 mt::fake_shared(event_sink));
1227
1228 session_manager.close_session(session);

Subscribers

People subscribed via source and target branches