Mir

Merge lp:~kdub/mir/notify-buffers-directly into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Cemil Azizoglu
Approved revision: no longer in the source branch.
Merged at revision: 3479
Proposed branch: lp:~kdub/mir/notify-buffers-directly
Merge into: lp:mir
Prerequisite: lp:~kdub/mir/notify-buffers-directly-groundwork
Diff against target: 1602 lines (+556/-299)
24 files modified
examples/render_surfaces.cpp (+3/-0)
include/server/mir/frontend/buffer_sink.h (+3/-0)
src/client/buffer_stream.cpp (+4/-5)
src/client/buffer_stream.h (+1/-1)
src/client/buffer_vault.cpp (+21/-25)
src/client/buffer_vault.h (+1/-1)
src/client/presentation_chain.cpp (+6/-39)
src/client/rpc/mir_protobuf_rpc_channel.cpp (+36/-4)
src/protobuf/mir_protobuf.proto (+8/-0)
src/protobuf/symbols.map (+4/-0)
src/server/compositor/buffer_map.cpp (+5/-3)
src/server/frontend/event_sender.cpp (+31/-1)
src/server/frontend/event_sender.h (+4/-0)
src/server/scene/global_event_sender.cpp (+12/-0)
src/server/scene/global_event_sender.h (+3/-0)
tests/include/mir/test/doubles/mock_event_sink.h (+4/-0)
tests/include/mir/test/doubles/null_event_sink.h (+4/-1)
tests/integration-tests/test_buffer_scheduling.cpp (+81/-19)
tests/mir_test_doubles/mock_event_sink_factory.cpp (+18/-0)
tests/unit-tests/client/test_buffer_vault.cpp (+99/-90)
tests/unit-tests/client/test_client_buffer_stream.cpp (+20/-1)
tests/unit-tests/client/test_presentation_chain.cpp (+43/-102)
tests/unit-tests/client/test_protobuf_rpc_channel.cpp (+138/-0)
tests/unit-tests/compositor/test_client_buffers.cpp (+7/-7)
To merge this branch: bzr merge lp:~kdub/mir/notify-buffers-directly
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Alan Griffiths Abstain
Cemil Azizoglu (community) conceptual Approve
Review via email: mp+291522@code.launchpad.net

Commit message

client: send incoming asynchronous buffer messages directly to the mcl::Buffer object. Prepares the buffers to be allocated from the connection, instead of a chain/stream.

Change the async protocol a bit too so the RPC channel can manage the async buffers better. The RPC allocate/free buffer calls are not synchronized with the async buffer sending, so the server has to be a bit more explicit about what operation its performing, so the client side rpc channel can clean up the buffers better.

So the notification chains go from:
OBS (buffer_stream):
rpc -> buffer_stream
NBS (buffer_stream):
rpc -> buffer_stream
NBS: (presentation_chain):
rpc -> buffer_stream -> buffer

to:

OBS (buffer_stream):
rpc -> buffer_stream
NBS (buffer_stream):
rpc -> buffer -> buffer_stream
NBS: (presentation_chain):
rpc -> buffer

Description of the change

client: send incoming asynchronous buffer messages directly to the mcl::Buffer object. Prepares the buffers to be allocated from the connection, instead of a chain/stream.

Change the async protocol a bit too so the RPC channel can manage the async buffers better. The RPC allocate/free buffer calls are not synchronized with the async buffer sending, so the server has to be a bit more explicit about what operation its performing, so the client side rpc channel can clean up the buffers better.

So the notification chains go from:
OBS (buffer_stream):
rpc -> buffer_stream
NBS (buffer_stream):
rpc -> buffer_stream
NBS: (presentation_chain):
rpc -> buffer_stream -> buffer

to:

OBS (buffer_stream):
rpc -> buffer_stream
NBS (buffer_stream):
rpc -> buffer -> buffer_stream
NBS: (presentation_chain):
rpc -> buffer

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

FAILED: Continuous integration, rev:3433
https://mir-jenkins.ubuntu.com/job/mir-ci/806/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/804/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/841
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/832
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/832
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/813/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/813/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/813/console
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/813/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/813
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/813/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/813/console

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

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

FAILED: Continuous integration, rev:3434
https://mir-jenkins.ubuntu.com/job/mir-ci/810/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/809/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/846
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/837
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/837
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/818
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/818/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/818
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/818/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/818/console
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/818/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/818
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/818/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/818
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/818/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

^^^

17:47:56 Slave went offline during the build

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

successful rerun, not sure if jenkins will revote on the MP or not:
https://mir-jenkins.ubuntu.com/job/device-runtests-mir/454/

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

FAILED: Continuous integration, rev:3434
https://mir-jenkins.ubuntu.com/job/mir-ci/818/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/822/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/859
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/850
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/850
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/832
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/832/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/832
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/832/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/832
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/832/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/832
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/832/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/832/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

17:45:22 11: [ FAILED ] MirSurfaceVisibilityEvent.exposed_received_when_surface_raised_over_occluding_surface (969 ms)
unrelated

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

PASSED: Continuous integration, rev:3434
https://mir-jenkins.ubuntu.com/job/mir-ci/824/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/829
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/866
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/857
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/857
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/839
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/839/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/839
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/839/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/839
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/839/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/839
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/839/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/839
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/839/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Heh. Our internal interfaces could do with some documentation... What *is* a BufferSink? What should an implementation of it do? send_buffer is reasonably self explanatory, but what is update_buffer expected to do? What is add/remove buffer expected to do?

493 +void ms::GlobalEventSender::add_buffer(graphics::Buffer&)
494 +{
495 +}

Bah. GlobalEventSender accumulates more lies. There probably needs to be some refactory so that GlobalEventSender doesn't have so many do-nothing non-implementations.

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

Conceptually ok.

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

+ virtual void add_buffer(graphics::Buffer&) = 0;
+ virtual void remove_buffer(graphics::Buffer&) = 0;
+ virtual void update_buffer(graphics::Buffer&) = 0;

These seem like very odd member functions to see on a "sink".

Also, it seems odd to see them taking a non-const reference.

I've not got any constructive suggestions right now, but I feel there must be a better way.

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

notify_buffer_allocation()
notify_buffer_update()
notify_buffer_release()
?

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

PASSED: Continuous integration, rev:3436
https://mir-jenkins.ubuntu.com/job/mir-ci/854/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/873
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/910
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/901
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/901
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/883
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=vivid+overlay/883/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/883
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/883/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/883
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/883/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/883
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/883/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/883
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/883/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
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/render_surfaces.cpp'
2--- examples/render_surfaces.cpp 2016-04-15 03:41:28 +0000
3+++ examples/render_surfaces.cpp 2016-04-18 17:46:27 +0000
4@@ -373,6 +373,9 @@
5 struct NullBufferSink : mf::BufferSink
6 {
7 void send_buffer(mf::BufferStreamId, mg::Buffer&, mg::BufferIpcMsgType) override {}
8+ void add_buffer(mg::Buffer&) override {}
9+ void remove_buffer(mg::Buffer&) override {}
10+ void update_buffer(mg::Buffer&) override {}
11 };
12
13 auto const stream = buffer_stream_factory->create_buffer_stream(
14
15=== modified file 'include/server/mir/frontend/buffer_sink.h'
16--- include/server/mir/frontend/buffer_sink.h 2015-07-20 14:54:01 +0000
17+++ include/server/mir/frontend/buffer_sink.h 2016-04-18 17:46:27 +0000
18@@ -33,6 +33,9 @@
19 virtual ~BufferSink() = default;
20
21 virtual void send_buffer(frontend::BufferStreamId id, graphics::Buffer& buffer, graphics::BufferIpcMsgType) = 0;
22+ virtual void add_buffer(graphics::Buffer&) = 0;
23+ virtual void remove_buffer(graphics::Buffer&) = 0;
24+ virtual void update_buffer(graphics::Buffer&) = 0;
25
26 protected:
27 BufferSink() = default;
28
29=== modified file 'src/client/buffer_stream.cpp'
30--- src/client/buffer_stream.cpp 2016-04-18 17:46:26 +0000
31+++ src/client/buffer_stream.cpp 2016-04-18 17:46:27 +0000
32@@ -303,9 +303,8 @@
33 {
34 }
35
36- void deposit(mp::Buffer const& buffer, mir::optional_value<geom::Size>, MirPixelFormat) override
37+ void deposit(mp::Buffer const&, mir::optional_value<geom::Size>, MirPixelFormat) override
38 {
39- vault.wire_transfer_inbound(buffer);
40 }
41
42 void advance_current_buffer(std::unique_lock<std::mutex>& lk)
43@@ -412,7 +411,7 @@
44 std::shared_ptr<MirWaitHandle> creation_wait_handle,
45 mclr::DisplayServer& server,
46 std::shared_ptr<mcl::ClientPlatform> const& client_platform,
47- std::weak_ptr<mcl::SurfaceMap> const&,
48+ std::weak_ptr<mcl::SurfaceMap> const& map,
49 std::shared_ptr<mcl::AsyncBufferFactory> const& factory,
50 mp::BufferStream const& a_protobuf_bs,
51 std::shared_ptr<mcl::PerfReport> const& perf_report,
52@@ -429,7 +428,7 @@
53 ideal_buffer_size(ideal_size),
54 nbuffers(nbuffers),
55 creation_wait_handle(creation_wait_handle),
56- map(std::make_shared<mcl::ConnectionSurfaceMap>()),
57+ map(map),
58 factory(factory)
59 {
60 init_swap_interval();
61@@ -457,7 +456,7 @@
62 else
63 {
64 buffer_depository = std::make_unique<NewBufferSemantics>(
65- client_platform->create_buffer_factory(), std::make_shared<mcl::BufferFactory>(),
66+ client_platform->create_buffer_factory(), factory,
67 std::make_shared<Requests>(display_server, protobuf_bs->id().value()), map,
68 ideal_buffer_size, static_cast<MirPixelFormat>(protobuf_bs->pixel_format()),
69 protobuf_bs->buffer_usage(), nbuffers);
70
71=== modified file 'src/client/buffer_stream.h'
72--- src/client/buffer_stream.h 2016-04-18 17:46:26 +0000
73+++ src/client/buffer_stream.h 2016-04-18 17:46:27 +0000
74@@ -165,7 +165,7 @@
75 size_t const nbuffers;
76 std::string error_message;
77 std::shared_ptr<MirWaitHandle> creation_wait_handle;
78- std::shared_ptr<SurfaceMap> const map;
79+ std::weak_ptr<SurfaceMap> const map;
80 std::shared_ptr<AsyncBufferFactory> const factory;
81 };
82
83
84=== modified file 'src/client/buffer_vault.cpp'
85--- src/client/buffer_vault.cpp 2016-04-04 03:30:04 +0000
86+++ src/client/buffer_vault.cpp 2016-04-18 17:46:27 +0000
87@@ -24,6 +24,9 @@
88 #include "surface_map.h"
89 #include "mir_protobuf.pb.h"
90 #include "protobuf_to_native_buffer.h"
91+#include "connection_surface_map.h"
92+#include "buffer_factory.h"
93+#include "buffer.h"
94 #include <algorithm>
95 #include <boost/throw_exception.hpp>
96
97@@ -42,8 +45,10 @@
98
99 namespace
100 {
101-void ignore(MirPresentationChain*, MirBuffer*, void*)
102+void incoming_buffer(MirPresentationChain*, MirBuffer* buffer, void* context)
103 {
104+ auto vault = static_cast<mcl::BufferVault*>(context);
105+ vault->wire_transfer_inbound(reinterpret_cast<mcl::Buffer*>(buffer)->rpc_id());
106 }
107 }
108
109@@ -74,6 +79,7 @@
110 if (disconnected_)
111 return;
112
113+ buffer_factory->cancel_requests_with_context(this);
114 for (auto& it : buffers)
115 try
116 {
117@@ -86,7 +92,8 @@
118
119 void mcl::BufferVault::alloc_buffer(geom::Size size, MirPixelFormat format, int usage)
120 {
121- buffer_factory->expect_buffer(platform_factory, nullptr, size, format, (MirBufferUsage)usage, ignore, nullptr);
122+ buffer_factory->expect_buffer(platform_factory, nullptr, size, format, static_cast<MirBufferUsage>(usage),
123+ incoming_buffer, this);
124 server_requests->allocate_buffer(size, format, usage);
125 }
126
127@@ -116,6 +123,8 @@
128 mcl::NoTLSFuture<std::shared_ptr<mcl::Buffer>> mcl::BufferVault::withdraw()
129 {
130 std::lock_guard<std::mutex> lk(mutex);
131+ if (disconnected_)
132+ BOOST_THROW_EXCEPTION(std::logic_error("server_disconnected"));
133 mcl::NoTLSPromise<std::shared_ptr<mcl::Buffer>> promise;
134 auto it = std::find_if(buffers.begin(), buffers.end(),
135 [this](std::pair<int, Owner> const& entry) {
136@@ -160,42 +169,29 @@
137 server_requests->submit_buffer(*buffer);
138 }
139
140-void mcl::BufferVault::wire_transfer_inbound(mp::Buffer const& protobuf_buffer)
141+void mcl::BufferVault::wire_transfer_inbound(int buffer_id)
142 {
143- std::shared_ptr<MirBufferPackage> package = mcl::protobuf_to_native_buffer(protobuf_buffer);
144- std::shared_ptr<mcl::Buffer> buffer;
145 std::unique_lock<std::mutex> lk(mutex);
146- auto it = buffers.find(protobuf_buffer.buffer_id());
147+
148+ auto buffer = checked_buffer_from_map(buffer_id);
149+ auto inbound_size = buffer->size();
150+ auto it = buffers.find(buffer_id);
151 if (it == buffers.end())
152 {
153- geom::Size sz{package->width, package->height};
154- if (sz != size)
155+ if (inbound_size != size)
156 {
157 lk.unlock();
158- for (int i = 0; i != package->fd_items; ++i)
159- close(package->fd[i]);
160-
161- realloc_buffer(protobuf_buffer.buffer_id(), size, format, usage);
162+ realloc_buffer(buffer_id, size, format, usage);
163 return;
164 }
165-
166- buffer = buffer_factory->generate_buffer(protobuf_buffer);
167- if (auto map = surface_map.lock())
168- map->insert(protobuf_buffer.buffer_id(), buffer);
169- else
170- BOOST_THROW_EXCEPTION(std::logic_error("connection resources lost; cannot access buffer"));
171-
172- buffers[protobuf_buffer.buffer_id()] = Owner::Self;
173- buffer->received();
174+ buffers[buffer_id] = Owner::Self;
175 }
176 else
177 {
178- buffer = checked_buffer_from_map(protobuf_buffer.buffer_id());
179- buffer->received(*package);
180 auto should_decrease_count = (current_buffer_count > needed_buffer_count);
181 if (size != buffer->size() || should_decrease_count)
182 {
183- int id = it->first;
184+ auto id = it->first;
185 buffers.erase(it);
186 lk.unlock();
187
188@@ -214,7 +210,7 @@
189
190 if (!promises.empty())
191 {
192- buffers[protobuf_buffer.buffer_id()] = Owner::ContentProducer;
193+ buffers[buffer_id] = Owner::ContentProducer;
194 promises.front().set_value(buffer);
195 promises.pop_front();
196 }
197
198=== modified file 'src/client/buffer_vault.h'
199--- src/client/buffer_vault.h 2016-04-04 03:30:04 +0000
200+++ src/client/buffer_vault.h 2016-04-18 17:46:27 +0000
201@@ -66,7 +66,7 @@
202
203 NoTLSFuture<std::shared_ptr<Buffer>> withdraw();
204 void deposit(std::shared_ptr<Buffer> const& buffer);
205- void wire_transfer_inbound(protobuf::Buffer const&);
206+ void wire_transfer_inbound(int buffer_id);
207 void wire_transfer_outbound(std::shared_ptr<Buffer> const& buffer);
208 void set_size(geometry::Size);
209 void disconnected();
210
211=== modified file 'src/client/presentation_chain.cpp'
212--- src/client/presentation_chain.cpp 2016-03-23 06:39:56 +0000
213+++ src/client/presentation_chain.cpp 2016-04-18 17:46:27 +0000
214@@ -78,16 +78,9 @@
215 {
216 mp::BufferRequest request;
217 {
218- std::lock_guard<decltype(mutex)> lk(mutex);
219- auto buffer_it = std::find_if(buffers.begin(), buffers.end(),
220- [&buffer](std::unique_ptr<Buffer> const& it)
221- { return reinterpret_cast<MirBuffer*>(it.get()) == buffer; });
222- if (buffer_it == buffers.end())
223- BOOST_THROW_EXCEPTION(std::logic_error("unknown buffer"));
224-
225 request.mutable_id()->set_value(stream_id);
226- request.mutable_buffer()->set_buffer_id((*buffer_it)->rpc_id());
227- (*buffer_it)->submitted();
228+ request.mutable_buffer()->set_buffer_id(reinterpret_cast<mcl::Buffer*>(buffer)->rpc_id());
229+ reinterpret_cast<mcl::Buffer*>(buffer)->submitted();
230 }
231
232 auto ignored = new mp::Void;
233@@ -97,42 +90,16 @@
234 void mcl::PresentationChain::release_buffer(MirBuffer* buffer)
235 {
236 mp::BufferRelease request;
237- {
238- std::lock_guard<decltype(mutex)> lk(mutex);
239- auto buffer_it = std::find_if(buffers.begin(), buffers.end(),
240- [&buffer](std::unique_ptr<Buffer> const& it)
241- { return reinterpret_cast<MirBuffer*>(it.get()) == buffer; });
242- if (buffer_it == buffers.end())
243- BOOST_THROW_EXCEPTION(std::logic_error("unknown buffer"));
244-
245- request.mutable_id()->set_value(stream_id);
246- auto buffer_req = request.add_buffers();
247- buffer_req->set_buffer_id((*buffer_it)->rpc_id());
248-
249- buffers.erase(buffer_it);
250- }
251+ request.mutable_id()->set_value(stream_id);
252+ auto buffer_req = request.add_buffers();
253+ buffer_req->set_buffer_id(reinterpret_cast<mcl::Buffer*>(buffer)->rpc_id());
254
255 auto ignored = new mp::Void;
256 server.release_buffers(&request, ignored, gp::NewCallback(ignore_response, ignored));
257 }
258
259-void mcl::PresentationChain::buffer_available(mp::Buffer const& buffer)
260+void mcl::PresentationChain::buffer_available(mp::Buffer const&)
261 {
262- std::lock_guard<decltype(mutex)> lk(mutex);
263- //first see if this buffer has been here before
264- std::shared_ptr<MirBufferPackage> package = mcl::protobuf_to_native_buffer(buffer);
265- auto buffer_it = std::find_if(buffers.begin(), buffers.end(),
266- [&buffer](std::unique_ptr<Buffer> const& b)
267- { return buffer.buffer_id() == b->rpc_id(); });
268- if (buffer_it != buffers.end())
269- {
270- (*buffer_it)->received(*package);
271- }
272- else
273- {
274- buffers.emplace_back(mir_buffer_factory->generate_buffer(buffer));
275- buffers.back()->received();
276- }
277 }
278
279 void mcl::PresentationChain::buffer_unavailable()
280
281=== modified file 'src/client/rpc/mir_protobuf_rpc_channel.cpp'
282--- src/client/rpc/mir_protobuf_rpc_channel.cpp 2016-04-04 03:30:04 +0000
283+++ src/client/rpc/mir_protobuf_rpc_channel.cpp 2016-04-18 17:46:27 +0000
284@@ -20,11 +20,15 @@
285 #include "rpc_report.h"
286
287 #include "../surface_map.h"
288+#include "../buffer.h"
289+#include "../presentation_chain.h"
290+#include "../buffer_factory.h"
291 #include "../mir_surface.h"
292 #include "../display_configuration.h"
293 #include "../lifecycle_control.h"
294 #include "../event_sink.h"
295 #include "../make_protobuf_object.h"
296+#include "../protobuf_to_native_buffer.h"
297 #include "mir/input/input_devices.h"
298 #include "mir/variable_length_array.h"
299 #include "mir/events/event_builders.h"
300@@ -35,6 +39,7 @@
301 #include "mir_protobuf_wire.pb.h"
302
303 #include <boost/bind.hpp>
304+#include <boost/throw_exception.hpp>
305 #include <endian.h>
306
307 #include <stdexcept>
308@@ -304,10 +309,37 @@
309 {
310 try
311 {
312- map->with_stream_do(mf::BufferStreamId(seq.buffer_request().id().value()),
313- [&] (mcl::BufferReceiver* receiver) {
314- receiver->buffer_available(seq.buffer_request().buffer());
315- });
316+ if (seq.buffer_request().has_id())
317+ {
318+ map->with_stream_do(mf::BufferStreamId(seq.buffer_request().id().value()),
319+ [&] (mcl::BufferReceiver* receiver) {
320+ receiver->buffer_available(seq.buffer_request().buffer());
321+ });
322+ }
323+
324+ else if (seq.buffer_request().has_operation())
325+ {
326+ auto stream_cmd = seq.buffer_request().operation();
327+ auto buffer_id = seq.buffer_request().buffer().buffer_id();
328+ std::shared_ptr<mcl::Buffer> buffer;
329+ switch (stream_cmd)
330+ {
331+ case mp::BufferOperation::add:
332+ buffer = buffer_factory->generate_buffer(seq.buffer_request().buffer());
333+ map->insert(buffer_id, buffer);
334+ buffer->received();
335+ break;
336+ case mp::BufferOperation::update:
337+ map->buffer(buffer_id)->received(
338+ *mcl::protobuf_to_native_buffer(seq.buffer_request().buffer()));
339+ break;
340+ case mp::BufferOperation::remove:
341+ map->erase(buffer_id);
342+ break;
343+ default:
344+ BOOST_THROW_EXCEPTION(std::runtime_error("unknown buffer operation"));
345+ }
346+ }
347 }
348 catch (std::exception& e)
349 {
350
351=== modified file 'src/protobuf/mir_protobuf.proto'
352--- src/protobuf/mir_protobuf.proto 2016-04-14 05:37:22 +0000
353+++ src/protobuf/mir_protobuf.proto 2016-04-18 17:46:27 +0000
354@@ -137,9 +137,17 @@
355 optional BufferStreamId id = 2;
356 };
357
358+enum BufferOperation
359+{
360+ add = 0;
361+ update = 1;
362+ remove = 2;
363+};
364+
365 message BufferRequest {
366 optional BufferStreamId id = 1;
367 optional Buffer buffer = 2;
368+ optional BufferOperation operation = 3;
369 };
370
371 message Buffer {
372
373=== modified file 'src/protobuf/symbols.map'
374--- src/protobuf/symbols.map 2016-04-13 00:58:26 +0000
375+++ src/protobuf/symbols.map 2016-04-18 17:46:27 +0000
376@@ -40,6 +40,10 @@
377 mir::protobuf::Buffer::MergeFrom*;
378 mir::protobuf::Buffer::MergePartialFromCodedStream*;
379 mir::protobuf::Buffer::New*;
380+ mir::protobuf::BufferOperation_IsValid*;
381+ mir::protobuf::BufferOperation_MIN*;
382+ mir::protobuf::BufferOperation_ARRAYSIZE*;
383+ mir::protobuf::BufferOperation_MAX*;
384 mir::protobuf::BufferRelease::?BufferRelease*;
385 mir::protobuf::BufferRelease::BufferRelease*;
386 mir::protobuf::BufferRelease::ByteSize*;
387
388=== modified file 'src/server/compositor/buffer_map.cpp'
389--- src/server/compositor/buffer_map.cpp 2016-04-05 03:47:49 +0000
390+++ src/server/compositor/buffer_map.cpp 2016-04-18 17:46:27 +0000
391@@ -53,14 +53,16 @@
392 std::unique_lock<decltype(mutex)> lk(mutex);
393 auto buffer = allocator->alloc_buffer(properties);
394 buffers[buffer->id()] = {buffer, Owner::client};
395- sink->send_buffer(stream_id, *buffer, mg::BufferIpcMsgType::full_msg);
396+ sink->add_buffer(*buffer);
397 return buffer->id();
398 }
399
400 void mc::BufferMap::remove_buffer(mg::BufferID id)
401 {
402 std::unique_lock<decltype(mutex)> lk(mutex);
403- buffers.erase(checked_buffers_find(id, lk));
404+ auto it = checked_buffers_find(id, lk);
405+ sink->remove_buffer(*it->second.buffer);
406+ buffers.erase(it);
407 }
408
409 void mc::BufferMap::send_buffer(mg::BufferID id)
410@@ -72,7 +74,7 @@
411 auto buffer = it->second.buffer;
412 it->second.owner = Owner::client;
413 lk.unlock();
414- sink->send_buffer(stream_id, *buffer, mg::BufferIpcMsgType::update_msg);
415+ sink->update_buffer(*buffer);
416 }
417 }
418
419
420=== modified file 'src/server/frontend/event_sender.cpp'
421--- src/server/frontend/event_sender.cpp 2016-01-29 08:18:22 +0000
422+++ src/server/frontend/event_sender.cpp 2016-04-18 17:46:27 +0000
423@@ -128,11 +128,41 @@
424 }
425 }
426
427+void mfd::EventSender::add_buffer(graphics::Buffer& buffer)
428+{
429+ mp::EventSequence seq;
430+ auto request = seq.mutable_buffer_request();
431+ request->set_operation(mir::protobuf::BufferOperation::add);
432+ send_buffer(seq, buffer, mg::BufferIpcMsgType::full_msg);
433+}
434+
435+void mfd::EventSender::remove_buffer(graphics::Buffer& buffer)
436+{
437+ mp::EventSequence seq;
438+ auto request = seq.mutable_buffer_request();
439+ request->set_operation(mir::protobuf::BufferOperation::remove);
440+ send_buffer(seq, buffer, mg::BufferIpcMsgType::update_msg);
441+}
442+
443+void mfd::EventSender::update_buffer(graphics::Buffer& buffer)
444+{
445+ mp::EventSequence seq;
446+ auto request = seq.mutable_buffer_request();
447+ request->set_operation(mir::protobuf::BufferOperation::update);
448+ send_buffer(seq, buffer, mg::BufferIpcMsgType::update_msg);
449+}
450+
451 void mfd::EventSender::send_buffer(frontend::BufferStreamId id, graphics::Buffer& buffer, mg::BufferIpcMsgType type)
452 {
453 mp::EventSequence seq;
454 auto request = seq.mutable_buffer_request();
455- request->mutable_id()->set_value(id.as_value());
456+ request->mutable_id()->set_value(id.as_value());
457+ send_buffer(seq, buffer, type);
458+}
459+
460+void mfd::EventSender::send_buffer(mp::EventSequence& seq, graphics::Buffer& buffer, mg::BufferIpcMsgType type)
461+{
462+ auto request = seq.mutable_buffer_request();
463 request->mutable_buffer()->set_buffer_id(buffer.id().as_value());
464
465 mfd::ProtobufBufferPacker request_msg{const_cast<mir::protobuf::Buffer*>(request->mutable_buffer())};
466
467=== modified file 'src/server/frontend/event_sender.h'
468--- src/server/frontend/event_sender.h 2016-01-29 08:18:22 +0000
469+++ src/server/frontend/event_sender.h 2016-04-18 17:46:27 +0000
470@@ -49,9 +49,13 @@
471 void handle_input_device_change(std::vector<std::shared_ptr<mir::input::Device>> const& devices) override;
472 void send_ping(int32_t serial) override;
473 void send_buffer(frontend::BufferStreamId id, graphics::Buffer& buffer, graphics::BufferIpcMsgType) override;
474+ void add_buffer(graphics::Buffer&) override;
475+ void remove_buffer(graphics::Buffer&) override;
476+ void update_buffer(graphics::Buffer&) override;
477
478 private:
479 void send_event_sequence(protobuf::EventSequence&, FdSets const&);
480+ void send_buffer(protobuf::EventSequence&, graphics::Buffer&, graphics::BufferIpcMsgType);
481
482 std::shared_ptr<MessageSender> const sender;
483 std::shared_ptr<graphics::PlatformIpcOperations> const buffer_packer;
484
485=== modified file 'src/server/scene/global_event_sender.cpp'
486--- src/server/scene/global_event_sender.cpp 2016-01-29 08:18:22 +0000
487+++ src/server/scene/global_event_sender.cpp 2016-04-18 17:46:27 +0000
488@@ -63,3 +63,15 @@
489 void ms::GlobalEventSender::send_buffer(mir::frontend::BufferStreamId, mg::Buffer&, mg::BufferIpcMsgType)
490 {
491 }
492+
493+void ms::GlobalEventSender::add_buffer(graphics::Buffer&)
494+{
495+}
496+
497+void ms::GlobalEventSender::remove_buffer(graphics::Buffer&)
498+{
499+}
500+
501+void ms::GlobalEventSender::update_buffer(graphics::Buffer&)
502+{
503+}
504
505=== modified file 'src/server/scene/global_event_sender.h'
506--- src/server/scene/global_event_sender.h 2016-01-29 08:18:22 +0000
507+++ src/server/scene/global_event_sender.h 2016-04-18 17:46:27 +0000
508@@ -39,6 +39,9 @@
509 void handle_input_device_change(std::vector<std::shared_ptr<mir::input::Device>> const& devices) override;
510 void send_ping(int32_t serial) override;
511 void send_buffer(frontend::BufferStreamId id, graphics::Buffer& buffer, graphics::BufferIpcMsgType) override;
512+ void add_buffer(graphics::Buffer&) override;
513+ void remove_buffer(graphics::Buffer&) override;
514+ void update_buffer(graphics::Buffer&) override;
515
516 private:
517 std::shared_ptr<SessionContainer> const sessions;
518
519=== modified file 'tests/include/mir/test/doubles/mock_event_sink.h'
520--- tests/include/mir/test/doubles/mock_event_sink.h 2016-01-29 08:18:22 +0000
521+++ tests/include/mir/test/doubles/mock_event_sink.h 2016-04-18 17:46:27 +0000
522@@ -39,6 +39,10 @@
523 MOCK_METHOD1(handle_display_config_change, void(graphics::DisplayConfiguration const&));
524 MOCK_METHOD1(send_ping, void(int32_t));
525 MOCK_METHOD3(send_buffer, void(frontend::BufferStreamId, graphics::Buffer&, graphics::BufferIpcMsgType));
526+ MOCK_METHOD1(add_buffer, void(graphics::Buffer&));
527+ MOCK_METHOD1(remove_buffer, void(graphics::Buffer&));
528+ MOCK_METHOD1(update_buffer, void(graphics::Buffer&));
529+
530 MOCK_METHOD1(handle_input_device_change, void(std::vector<std::shared_ptr<input::Device>> const&));
531 };
532 }
533
534=== modified file 'tests/include/mir/test/doubles/null_event_sink.h'
535--- tests/include/mir/test/doubles/null_event_sink.h 2016-01-29 08:18:22 +0000
536+++ tests/include/mir/test/doubles/null_event_sink.h 2016-04-18 17:46:27 +0000
537@@ -41,7 +41,10 @@
538 void handle_display_config_change(graphics::DisplayConfiguration const&) override {}
539 void send_ping(int32_t) override {}
540 void send_buffer(frontend::BufferStreamId, graphics::Buffer&, graphics::BufferIpcMsgType) override {}
541- void handle_input_device_change(std::vector<std::shared_ptr<mir::input::Device>> const&) override {};
542+ void handle_input_device_change(std::vector<std::shared_ptr<mir::input::Device>> const&) override {}
543+ void add_buffer(graphics::Buffer&) override {}
544+ void remove_buffer(graphics::Buffer&) override {}
545+ void update_buffer(graphics::Buffer&) override {}
546 };
547
548 std::unique_ptr<frontend::EventSink> null_sink_factory(std::shared_ptr<frontend::MessageSender> const&);
549
550=== modified file 'tests/integration-tests/test_buffer_scheduling.cpp'
551--- tests/integration-tests/test_buffer_scheduling.cpp 2016-04-06 08:44:01 +0000
552+++ tests/integration-tests/test_buffer_scheduling.cpp 2016-04-18 17:46:27 +0000
553@@ -22,6 +22,8 @@
554 #include "src/client/buffer_vault.h"
555 #include "src/client/buffer_factory.h"
556 #include "src/client/client_buffer_depository.h"
557+#include "src/client/buffer_factory.h"
558+#include "src/client/protobuf_to_native_buffer.h"
559 #include "src/client/connection_surface_map.h"
560 #include "src/server/compositor/buffer_queue.h"
561 #include "src/server/compositor/stream.h"
562@@ -222,7 +224,7 @@
563 server_bound_fn = fn;
564 }
565
566- void on_client_bound_transfer(std::function<void(mp::Buffer&)> fn)
567+ void on_client_bound_transfer(std::function<void(mp::BufferRequest&)> fn)
568 {
569 client_bound_fn = fn;
570 for(auto& b : buffers)
571@@ -257,12 +259,12 @@
572 return last_submit;
573 }
574
575- void client_bound_transfer(mp::Buffer& buffer)
576+ void client_bound_transfer(mp::BufferRequest& request)
577 {
578 if (client_bound_fn)
579- client_bound_fn(buffer);
580+ client_bound_fn(request);
581 else
582- buffers.push_back(buffer);
583+ buffers.push_back(request);
584 }
585
586 void allocate(geom::Size sz)
587@@ -273,10 +275,10 @@
588
589 std::function<void(geom::Size)> allocate_fn;
590 std::function<void(geom::Size)> resize_fn;
591- std::function<void(mp::Buffer&)> client_bound_fn;
592+ std::function<void(mp::BufferRequest&)> client_bound_fn;
593 std::function<void(mp::Buffer&)> server_bound_fn;
594
595- std::vector<mp::Buffer> buffers;
596+ std::vector<mp::BufferRequest> buffers;
597 int last_submit{0};
598 };
599
600@@ -287,13 +289,45 @@
601 {
602 }
603
604- void send_buffer(mf::BufferStreamId, mg::Buffer& buffer, mg::BufferIpcMsgType)
605- {
606- mp::Buffer protobuffer;
607- protobuffer.set_buffer_id(buffer.id().as_value());
608- protobuffer.set_width(buffer.size().width.as_int());
609- protobuffer.set_height(buffer.size().height.as_int());
610- ipc->client_bound_transfer(protobuffer);
611+ void send_buffer(mf::BufferStreamId id, mg::Buffer& buffer, mg::BufferIpcMsgType)
612+ {
613+ mp::BufferRequest request;
614+ auto protobuffer = request.mutable_buffer();
615+ request.mutable_id()->set_value(id.as_value());
616+ protobuffer->set_buffer_id(buffer.id().as_value());
617+ protobuffer->set_width(buffer.size().width.as_int());
618+ protobuffer->set_height(buffer.size().height.as_int());
619+ ipc->client_bound_transfer(request);
620+ }
621+ void add_buffer(mg::Buffer& buffer)
622+ {
623+ mp::BufferRequest request;
624+ auto protobuffer = request.mutable_buffer();
625+ request.set_operation(mp::BufferOperation::add);
626+ protobuffer->set_buffer_id(buffer.id().as_value());
627+ protobuffer->set_width(buffer.size().width.as_int());
628+ protobuffer->set_height(buffer.size().height.as_int());
629+ ipc->client_bound_transfer(request);
630+ }
631+ void remove_buffer(mg::Buffer& buffer)
632+ {
633+ mp::BufferRequest request;
634+ auto protobuffer = request.mutable_buffer();
635+ request.set_operation(mp::BufferOperation::remove);
636+ protobuffer->set_buffer_id(buffer.id().as_value());
637+ protobuffer->set_width(buffer.size().width.as_int());
638+ protobuffer->set_height(buffer.size().height.as_int());
639+ ipc->client_bound_transfer(request);
640+ }
641+ void update_buffer(mg::Buffer& buffer)
642+ {
643+ mp::BufferRequest request;
644+ auto protobuffer = request.mutable_buffer();
645+ request.set_operation(mp::BufferOperation::update);
646+ protobuffer->set_buffer_id(buffer.id().as_value());
647+ protobuffer->set_width(buffer.size().width.as_int());
648+ protobuffer->set_height(buffer.size().height.as_int());
649+ ipc->client_bound_transfer(request);
650 }
651 void handle_event(MirEvent const&) {}
652 void handle_lifecycle_event(MirLifecycleState) {}
653@@ -371,16 +405,43 @@
654 ScheduledProducer(std::shared_ptr<StubIpcSystem> const& ipc_stub, int nbuffers) :
655 ipc(ipc_stub),
656 map(std::make_shared<mcl::ConnectionSurfaceMap>()),
657+ factory(std::make_shared<mcl::BufferFactory>()),
658 vault(
659- std::make_shared<mtd::StubClientBufferFactory>(),
660- std::make_shared<mcl::BufferFactory>(),
661- std::make_shared<ServerRequests>(ipc),
662- map,
663+ std::make_shared<mtd::StubClientBufferFactory>(), factory,
664+ std::make_shared<ServerRequests>(ipc), map,
665 geom::Size(100,100), mir_pixel_format_abgr_8888, 0, nbuffers)
666 {
667- ipc->on_client_bound_transfer([this](mp::Buffer& buffer){
668+ ipc->on_client_bound_transfer([this](mp::BufferRequest& request){
669+
670+ if (request.has_id())
671+ {
672+ auto& ipc_buffer = request.buffer();
673+ auto buffer = map->buffer(ipc_buffer.buffer_id());
674+ if (!buffer)
675+ {
676+ buffer = factory->generate_buffer(ipc_buffer);
677+ map->insert(ipc_buffer.buffer_id(), buffer);
678+ buffer->received();
679+ }
680+ else
681+ {
682+ buffer->received(*mcl::protobuf_to_native_buffer(ipc_buffer));
683+ }
684+ }
685+ else if (request.has_operation() && request.operation() == mp::BufferOperation::add)
686+ {
687+ auto& ipc_buffer = request.buffer();
688+ std::shared_ptr<mcl::Buffer> buffer = factory->generate_buffer(ipc_buffer);
689+ map->insert(request.buffer().buffer_id(), buffer);
690+ buffer->received();
691+ }
692+ else if (request.has_operation() && request.operation() == mp::BufferOperation::update)
693+ {
694+ auto buffer = map->buffer(request.buffer().buffer_id());
695+ buffer->received(*mcl::protobuf_to_native_buffer(request.buffer()));
696+ }
697 available++;
698- vault.wire_transfer_inbound(buffer);
699+
700 });
701 ipc->on_resize_event([this](geom::Size sz)
702 {
703@@ -434,6 +495,7 @@
704 std::vector<BufferEntry> entries;
705 std::shared_ptr<StubIpcSystem> ipc;
706 std::shared_ptr<mcl::SurfaceMap> const map;
707+ std::shared_ptr<mcl::BufferFactory> factory;
708 mcl::BufferVault vault;
709 int max, cur;
710 int available{0};
711
712=== modified file 'tests/mir_test_doubles/mock_event_sink_factory.cpp'
713--- tests/mir_test_doubles/mock_event_sink_factory.cpp 2016-01-29 08:18:22 +0000
714+++ tests/mir_test_doubles/mock_event_sink_factory.cpp 2016-04-18 17:46:27 +0000
715@@ -40,6 +40,9 @@
716 void send_ping(int32_t serial) override;
717 void send_buffer(mf::BufferStreamId id, mg::Buffer& buf, mg::BufferIpcMsgType type) override;
718 void handle_input_device_change(std::vector<std::shared_ptr<mir::input::Device>> const& devices) override;
719+ void add_buffer(mir::graphics::Buffer&) override;
720+ void remove_buffer(mir::graphics::Buffer&) override;
721+ void update_buffer(mir::graphics::Buffer&) override;
722
723 private:
724 std::shared_ptr<mf::EventSink> underlying_sink;
725@@ -90,6 +93,21 @@
726 underlying_sink->send_buffer(id, buf, type);
727 }
728
729+void GloballyUniqueMockEventSink::add_buffer(mir::graphics::Buffer& buffer)
730+{
731+ underlying_sink->add_buffer(buffer);
732+}
733+
734+void GloballyUniqueMockEventSink::remove_buffer(mir::graphics::Buffer& buffer)
735+{
736+ underlying_sink->remove_buffer(buffer);
737+}
738+
739+void GloballyUniqueMockEventSink::update_buffer(mir::graphics::Buffer& buffer)
740+{
741+ underlying_sink->update_buffer(buffer);
742+}
743+
744 mtd::MockEventSinkFactory::MockEventSinkFactory()
745 : underlying_sink{std::make_shared<testing::NiceMock<mtd::MockEventSink>>()}
746 {
747
748=== modified file 'tests/unit-tests/client/test_buffer_vault.cpp'
749--- tests/unit-tests/client/test_buffer_vault.cpp 2016-04-04 03:30:04 +0000
750+++ tests/unit-tests/client/test_buffer_vault.cpp 2016-04-18 17:46:27 +0000
751@@ -71,6 +71,10 @@
752 MOCK_METHOD0(disconnected, void());
753 };
754
755+void ignore(MirPresentationChain*, MirBuffer*, void*)
756+{
757+}
758+
759 struct BufferVault : public testing::Test
760 {
761 BufferVault() :
762@@ -82,10 +86,43 @@
763 package2.set_height(size.height.as_int());
764 package3.set_width(size.width.as_int());
765 package3.set_height(size.height.as_int());
766+ package4.set_width(new_size.width.as_int());
767+ package4.set_height(new_size.height.as_int());
768
769 package.set_buffer_id(1);
770 package2.set_buffer_id(2);
771 package3.set_buffer_id(3);
772+ package4.set_buffer_id(4);
773+
774+ auto buffer1 = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
775+ ON_CALL(*buffer1, size())
776+ .WillByDefault(Return(size));
777+ auto buffer2 = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
778+ ON_CALL(*buffer2, size())
779+ .WillByDefault(Return(size));
780+ auto buffer3 = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
781+ ON_CALL(*buffer3, size())
782+ .WillByDefault(Return(size));
783+ auto buffer4 = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
784+ ON_CALL(*buffer4, size())
785+ .WillByDefault(Return(new_size));
786+
787+ auto b1 = std::make_shared<mcl::Buffer>(
788+ ignore, nullptr, package.buffer_id(), buffer1, nullptr, mir_buffer_usage_software);
789+ auto b2 = std::make_shared<mcl::Buffer>(
790+ ignore, nullptr, package2.buffer_id(), buffer2, nullptr, mir_buffer_usage_software);
791+ auto b3 = std::make_shared<mcl::Buffer>(
792+ ignore, nullptr, package3.buffer_id(), buffer3, nullptr, mir_buffer_usage_software);
793+ auto b4 = std::make_shared<mcl::Buffer>(
794+ ignore, nullptr, package4.buffer_id(), buffer4, nullptr, mir_buffer_usage_software);
795+ surface_map->insert(package.buffer_id(), b1);
796+ surface_map->insert(package2.buffer_id(), b2);
797+ surface_map->insert(package3.buffer_id(), b3);
798+ surface_map->insert(package4.buffer_id(), b4);
799+ b1->received();
800+ b2->received();
801+ b3->received();
802+ b4->received();
803 }
804
805 std::unique_ptr<mcl::BufferVault> make_vault()
806@@ -100,6 +137,8 @@
807
808 unsigned int initial_nbuffers {3};
809 geom::Size size{271, 314};
810+ float scale = 2.0f;
811+ geom::Size new_size{ size * scale };
812 MirPixelFormat format{mir_pixel_format_abgr_8888};
813 int usage{0};
814 mg::BufferProperties initial_properties{
815@@ -111,15 +150,16 @@
816 mp::Buffer package;
817 mp::Buffer package2;
818 mp::Buffer package3;
819+ mp::Buffer package4;
820 };
821
822 struct StartedBufferVault : BufferVault
823 {
824 StartedBufferVault()
825 {
826- vault.wire_transfer_inbound(package);
827- vault.wire_transfer_inbound(package2);
828- vault.wire_transfer_inbound(package3);
829+ vault.wire_transfer_inbound(package.buffer_id());
830+ vault.wire_transfer_inbound(package2.buffer_id());
831+ vault.wire_transfer_inbound(package3.buffer_id());
832 }
833 mcl::BufferVault vault{
834 mt::fake_shared(mock_platform_factory), mt::fake_shared(buffer_factory),
835@@ -127,9 +167,6 @@
836 size, format, usage, initial_nbuffers};
837 };
838
839-void ignore(MirPresentationChain*, MirBuffer*, void*)
840-{
841-}
842 }
843
844 TEST_F(BufferVault, creates_all_buffers_on_start)
845@@ -144,32 +181,9 @@
846 EXPECT_CALL(mock_requests, free_buffer(package.buffer_id()));
847 EXPECT_CALL(mock_requests, free_buffer(package2.buffer_id()));
848 auto vault = make_vault();
849- vault->wire_transfer_inbound(package);
850- vault->wire_transfer_inbound(package2);
851-}
852-
853-TEST_F(BufferVault, creates_buffer_on_first_insertion)
854-{
855- EXPECT_CALL(mock_platform_factory, create_buffer(_,initial_properties.size,initial_properties.format));
856- auto vault = make_vault();
857- vault->wire_transfer_inbound(package);
858-}
859-
860-TEST_F(BufferVault, updates_buffer_on_subsequent_insertions)
861-{
862- auto mock_buffer = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
863- EXPECT_CALL(*mock_buffer, update_from(_));
864- ON_CALL(*mock_buffer, size())
865- .WillByDefault(Return(size));
866- ON_CALL(mock_platform_factory, create_buffer(_,_,_))
867- .WillByDefault(Return(mock_buffer));
868-
869- auto vault = make_vault();
870- vault->wire_transfer_inbound(package);
871- auto b = vault->withdraw().get();
872- vault->deposit(b);
873- vault->wire_transfer_outbound(b);
874- vault->wire_transfer_inbound(package);
875+
876+ vault->wire_transfer_inbound(package.buffer_id());
877+ vault->wire_transfer_inbound(package2.buffer_id());
878 }
879
880 TEST_F(BufferVault, withdrawing_and_never_filling_up_will_timeout)
881@@ -230,15 +244,12 @@
882 TEST_F(BufferVault, can_transfer_again_when_we_get_the_buffer)
883 {
884 auto vault = make_vault();
885- EXPECT_CALL(mock_platform_factory, create_buffer(_,initial_properties.size,initial_properties.format))
886- .Times(Exactly(1));
887- vault->wire_transfer_inbound(package);
888+ vault->wire_transfer_inbound(package.buffer_id());
889 auto buffer = vault->withdraw().get();
890 vault->deposit(buffer);
891 vault->wire_transfer_outbound(buffer);
892
893- //should just activate, not create the buffer
894- vault->wire_transfer_inbound(package);
895+ vault->wire_transfer_inbound(package.buffer_id());
896 auto buffer2 = vault->withdraw().get();
897 EXPECT_THAT(buffer, Eq(buffer2));
898 }
899@@ -256,8 +267,8 @@
900
901 auto f_buffer1 = vault->withdraw();
902 auto f_buffer2 = vault->withdraw();
903- vault->wire_transfer_inbound(package);
904- vault->wire_transfer_inbound(package2);
905+ vault->wire_transfer_inbound(package.buffer_id());
906+ vault->wire_transfer_inbound(package2.buffer_id());
907
908 auto buffer1 = f_buffer1.get();
909 auto buffer2 = f_buffer2.get();
910@@ -283,9 +294,12 @@
911 EXPECT_CALL(*mock_buffer, increment_age());
912 ON_CALL(mock_platform_factory, create_buffer(_,_,_))
913 .WillByDefault(Return(mock_buffer));
914+ auto b1 = std::make_shared<mcl::Buffer>(
915+ ignore, nullptr, package.buffer_id(), mock_buffer, nullptr, mir_buffer_usage_software);
916+ surface_map->insert(package.buffer_id(), b1);
917
918 auto vault = make_vault();
919- vault->wire_transfer_inbound(package);
920+ vault->wire_transfer_inbound(package.buffer_id());
921 vault->deposit(vault->withdraw().get());
922 }
923
924@@ -297,9 +311,13 @@
925 EXPECT_CALL(*mock_buffer, mark_as_submitted());
926 ON_CALL(mock_platform_factory, create_buffer(_,_,_))
927 .WillByDefault(Return(mock_buffer));
928+ auto b1 = std::make_shared<mcl::Buffer>(
929+ ignore, nullptr, package.buffer_id(), mock_buffer, nullptr, mir_buffer_usage_software);
930+ surface_map->insert(package.buffer_id(), b1);
931+ b1->received();
932
933 auto vault = make_vault();
934- vault->wire_transfer_inbound(package);
935+ vault->wire_transfer_inbound(package.buffer_id());
936
937 auto buffer = vault->withdraw().get();
938 vault->deposit(buffer);
939@@ -308,53 +326,36 @@
940
941 TEST_F(StartedBufferVault, reallocates_incoming_buffers_of_incorrect_size_with_immediate_response)
942 {
943- mp::Buffer package4;
944- geom::Size new_size{80, 100};
945 EXPECT_CALL(mock_requests, free_buffer(package.buffer_id()));
946 EXPECT_CALL(mock_requests, allocate_buffer(new_size,_,_))
947 .WillOnce(Invoke(
948- [&, this](geom::Size sz, MirPixelFormat, int)
949+ [&, this](geom::Size, MirPixelFormat, int)
950 {
951- package4.set_width(sz.width.as_int());
952- package4.set_height(sz.height.as_int());
953- package4.set_buffer_id(4);
954- vault.wire_transfer_inbound(package4);
955+ vault.wire_transfer_inbound(package4.buffer_id());
956 }));
957
958 vault.set_size(new_size);
959- vault.wire_transfer_inbound(package);
960+ vault.wire_transfer_inbound(package.buffer_id());
961 Mock::VerifyAndClearExpectations(&mock_requests);
962 }
963
964 TEST_F(StartedBufferVault, reallocates_incoming_buffers_of_incorrect_size_with_delayed_response)
965 {
966- geom::Size new_size{80, 100};
967- mp::Buffer package4;
968- package4.set_width(new_size.width.as_int());
969- package4.set_height(new_size.height.as_int());
970- package4.set_buffer_id(4);
971-
972 EXPECT_CALL(mock_requests, free_buffer(package.buffer_id()));
973 EXPECT_CALL(mock_requests, allocate_buffer(new_size,_,_));
974
975 vault.set_size(new_size);
976- vault.wire_transfer_inbound(package);
977- vault.wire_transfer_inbound(package4);
978+ vault.wire_transfer_inbound(package.buffer_id());
979+ vault.wire_transfer_inbound(package4.buffer_id());
980 EXPECT_THAT(vault.withdraw().get()->size(), Eq(new_size));
981 Mock::VerifyAndClearExpectations(&mock_requests);
982 }
983
984 TEST_F(StartedBufferVault, withdraw_gives_only_newly_sized_buffers_after_resize)
985 {
986- mp::Buffer package4;
987- geom::Size new_size{80, 100};
988- package4.set_width(new_size.width.as_int());
989- package4.set_height(new_size.height.as_int());
990- package4.set_buffer_id(4);
991-
992 vault.set_size(new_size);
993- vault.wire_transfer_inbound(package);
994- vault.wire_transfer_inbound(package4);
995+ vault.wire_transfer_inbound(package.buffer_id());
996+ vault.wire_transfer_inbound(package4.buffer_id());
997
998 EXPECT_THAT(vault.withdraw().get()->size(), Eq(new_size));
999 Mock::VerifyAndClearExpectations(&mock_requests);
1000@@ -376,16 +377,9 @@
1001
1002 TEST_F(StartedBufferVault, scaling_resizes_buffers_right_away)
1003 {
1004- mp::Buffer package4;
1005- float scale = 2.0f;
1006- geom::Size new_size = size * scale;
1007- package4.set_width(new_size.width.as_int());
1008- package4.set_height(new_size.height.as_int());
1009- package4.set_buffer_id(4);
1010-
1011 EXPECT_CALL(mock_requests, allocate_buffer(_,_,_))
1012 .WillOnce(InvokeWithoutArgs(
1013- [&]{vault.wire_transfer_inbound(package4);}));
1014+ [&]{ vault.wire_transfer_inbound(package4.buffer_id());}));
1015 auto b1 = vault.withdraw().get();
1016 auto b2 = vault.withdraw().get();
1017 vault.set_scale(scale);
1018@@ -412,7 +406,7 @@
1019 .WillOnce(Throw(std::runtime_error("")));
1020 EXPECT_NO_THROW({
1021 auto vault = make_vault();
1022- vault->wire_transfer_inbound(package);
1023+ vault->wire_transfer_inbound(package.buffer_id());
1024 });
1025 }
1026
1027@@ -426,26 +420,33 @@
1028 TEST_F(StartedBufferVault, buffer_count_remains_the_same_after_scaling)
1029 {
1030 std::array<mp::Buffer, 3> buffers;
1031- float scale = 2.0f;
1032- geom::Size new_size = size * scale;
1033
1034 int i = initial_nbuffers;
1035 for (auto& buffer : buffers)
1036 {
1037+ i++;
1038 buffer.set_width(new_size.width.as_int());
1039 buffer.set_height(new_size.height.as_int());
1040- buffer.set_buffer_id(i++);
1041+ buffer.set_buffer_id(i);
1042+
1043+ auto mcb = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
1044+ ON_CALL(*mcb, size())
1045+ .WillByDefault(Return(new_size));
1046+ auto b = std::make_shared<mcl::Buffer>(
1047+ ignore, nullptr, i, mcb, nullptr, mir_buffer_usage_software);
1048+ surface_map->insert(i, b);
1049+ b->received();
1050 }
1051
1052 //make sure we alloc 3 new ones and free 3 old ones
1053 EXPECT_CALL(mock_requests, allocate_buffer(_,_,_))
1054 .Times(initial_nbuffers)
1055 .WillOnce(InvokeWithoutArgs(
1056- [&]{vault.wire_transfer_inbound(buffers[0]);}))
1057- .WillOnce(InvokeWithoutArgs(
1058- [&]{vault.wire_transfer_inbound(buffers[1]);}))
1059- .WillOnce(InvokeWithoutArgs(
1060- [&]{vault.wire_transfer_inbound(buffers[2]);}));
1061+ [&]{vault.wire_transfer_inbound(buffers[0].buffer_id());}))
1062+ .WillOnce(InvokeWithoutArgs(
1063+ [&]{vault.wire_transfer_inbound(buffers[1].buffer_id());}))
1064+ .WillOnce(InvokeWithoutArgs(
1065+ [&]{vault.wire_transfer_inbound(buffers[2].buffer_id());}));
1066 EXPECT_CALL(mock_requests, free_buffer(_))
1067 .Times(initial_nbuffers);
1068
1069@@ -453,15 +454,16 @@
1070 vault.set_scale(scale);
1071 vault.deposit(buffer);
1072 vault.wire_transfer_outbound(buffer);
1073- vault.wire_transfer_inbound(package);
1074+ vault.wire_transfer_inbound(package.buffer_id());
1075
1076 for(auto i = 0; i < 100; i++)
1077 {
1078 auto b = vault.withdraw().get();
1079 EXPECT_THAT(b->size(), Eq(new_size));
1080 vault.deposit(b);
1081+ b->received();
1082 vault.wire_transfer_outbound(b);
1083- vault.wire_transfer_inbound(buffers[(i+1)%3]);
1084+ vault.wire_transfer_inbound(buffers[(i+1)%3].buffer_id());
1085 }
1086 Mock::VerifyAndClearExpectations(&mock_requests);
1087 }
1088@@ -475,9 +477,9 @@
1089 .Times(initial_nbuffers);
1090 EXPECT_CALL(mock_requests, allocate_buffer(_,_,_))
1091 .Times(initial_nbuffers);
1092- vault->wire_transfer_inbound(package);
1093- vault->wire_transfer_inbound(package2);
1094- vault->wire_transfer_inbound(package3);
1095+ vault->wire_transfer_inbound(package.buffer_id());
1096+ vault->wire_transfer_inbound(package2.buffer_id());
1097+ vault->wire_transfer_inbound(package3.buffer_id());
1098
1099 }
1100
1101@@ -516,6 +518,13 @@
1102 requested_buffer.set_width(size.width.as_int());
1103 requested_buffer.set_height(size.height.as_int());
1104 requested_buffer.set_buffer_id(4);
1105+ auto extra_native_buffer = std::make_shared<NiceMock<mtd::MockClientBuffer>>();
1106+ ON_CALL(*extra_native_buffer, size())
1107+ .WillByDefault(Return(size));
1108+ auto extra_buffer = std::make_shared<mcl::Buffer>(
1109+ ignore, nullptr, package4.buffer_id(), extra_native_buffer, nullptr, mir_buffer_usage_software);
1110+ surface_map->insert(package4.buffer_id(), extra_buffer);
1111+ extra_buffer->received();
1112
1113 EXPECT_CALL(mock_requests, allocate_buffer(_,_,_))
1114 .Times(1);
1115@@ -523,7 +532,7 @@
1116 .Times(1);
1117
1118 vault.increase_buffer_count();
1119- vault.wire_transfer_inbound(requested_buffer);
1120+ vault.wire_transfer_inbound(requested_buffer.buffer_id());
1121 auto b = vault.withdraw().get();
1122 vault.deposit(b);
1123 vault.wire_transfer_outbound(b);
1124@@ -541,7 +550,7 @@
1125 vault.wire_transfer_outbound(b);
1126
1127 vault.decrease_buffer_count();
1128- vault.wire_transfer_inbound(package);
1129- vault.wire_transfer_inbound(package2);
1130+ vault.wire_transfer_inbound(package.buffer_id());
1131+ vault.wire_transfer_inbound(package2.buffer_id());
1132 Mock::VerifyAndClearExpectations(&mock_requests);
1133 }
1134
1135=== modified file 'tests/unit-tests/client/test_client_buffer_stream.cpp'
1136--- tests/unit-tests/client/test_client_buffer_stream.cpp 2016-04-18 17:46:26 +0000
1137+++ tests/unit-tests/client/test_client_buffer_stream.cpp 2016-04-18 17:46:27 +0000
1138@@ -186,7 +186,24 @@
1139
1140 void async_buffer_arrives(mcl::ClientBufferStream& bs, mp::Buffer& buffer)
1141 {
1142- bs.buffer_available(buffer);
1143+ if (legacy_exchange_buffer)
1144+ {
1145+ bs.buffer_available(buffer);
1146+ }
1147+ else
1148+ {
1149+ try
1150+ {
1151+ map->buffer(buffer.buffer_id())->received(*mcl::protobuf_to_native_buffer(buffer));
1152+ }
1153+ catch (std::runtime_error& e)
1154+ {
1155+ auto bb = factory->generate_buffer(buffer);
1156+ auto braw = bb.get();
1157+ map->insert(buffer.buffer_id(), std::move(bb));
1158+ braw->received();
1159+ }
1160+ }
1161 }
1162
1163 std::shared_ptr<mcl::ConnectionSurfaceMap> map{std::make_shared<mcl::ConnectionSurfaceMap>()};
1164@@ -524,6 +541,8 @@
1165 {
1166 using namespace std::literals::chrono_literals;
1167 NiceMock<mtd::MockClientBuffer> mock_client_buffer;
1168+ ON_CALL(mock_client_buffer, size())
1169+ .WillByDefault(Return(size));
1170 ON_CALL(mock_factory, create_buffer(BufferPackageMatches(buffer_package),_,_))
1171 .WillByDefault(Return(mt::fake_shared(mock_client_buffer)));
1172 ON_CALL(mock_protobuf_server, submit_buffer(_,_,_))
1173
1174=== modified file 'tests/unit-tests/client/test_presentation_chain.cpp'
1175--- tests/unit-tests/client/test_presentation_chain.cpp 2016-03-23 06:39:56 +0000
1176+++ tests/unit-tests/client/test_presentation_chain.cpp 2016-04-18 17:46:27 +0000
1177@@ -138,13 +138,6 @@
1178 static_cast<BufferCallbackContext*>(context)->set_buffer(buffer);
1179 }
1180
1181-static void counting_buffer_callback(MirPresentationChain*, MirBuffer* buffer, void* context)
1182-{
1183- BufferCount* c = static_cast<BufferCount*>(context);
1184- c->buffer = buffer;
1185- c->count = c->count + 1;
1186-}
1187-
1188 TEST_F(PresentationChain, returns_associated_connection)
1189 {
1190 mcl::PresentationChain chain(
1191@@ -177,20 +170,18 @@
1192 EXPECT_CALL(mock_server, allocate_buffers(BufferAllocationMatches(mp_alloc),_,_))
1193 .WillOnce(mtd::RunProtobufClosure());
1194 EXPECT_CALL(*factory, create_buffer(_, size, format));
1195-
1196+
1197+ auto mir_buffer_factory = std::make_shared<mcl::BufferFactory>();
1198 mcl::PresentationChain chain(
1199 connection, rpc_id, mock_server,
1200- factory, std::make_shared<mcl::BufferFactory>());
1201+ factory, mir_buffer_factory);
1202 chain.allocate_buffer(size, format, usage, buffer_callback, &buffer);
1203
1204- EXPECT_FALSE(buffer.buffer_is_set());
1205-
1206 mp::Buffer ipc_buf;
1207 ipc_buf.set_width(size.width.as_int());
1208 ipc_buf.set_height(size.height.as_int());
1209- chain.buffer_available(ipc_buf);
1210-
1211- EXPECT_TRUE(buffer.wait_for_buffer());
1212+ auto mirbuffer = mir_buffer_factory->generate_buffer(ipc_buf);
1213+ EXPECT_THAT(mirbuffer, Ne(nullptr));
1214 }
1215
1216 TEST_F(PresentationChain, creates_correct_buffer_when_buffers_arrive)
1217@@ -224,25 +215,32 @@
1218 ipc_buf[i].set_height(sizes[i].height.as_int());
1219 }
1220
1221+ std::array<std::shared_ptr<mtd::MockClientBuffer>, num_buffers> client_buffers { {
1222+ std::make_shared<NiceMock<mtd::MockClientBuffer>>(),
1223+ std::make_shared<NiceMock<mtd::MockClientBuffer>>(),
1224+ std::make_shared<NiceMock<mtd::MockClientBuffer>>()
1225+ } };
1226+
1227+ for(auto i = 0u; i < client_buffers.size(); i++)
1228+ {
1229+ EXPECT_CALL(*factory, create_buffer(_, sizes[i], _))
1230+ .WillOnce(Return(client_buffers[i]));
1231+ }
1232+
1233+ auto mir_buffer_factory = std::make_shared<mcl::BufferFactory>();
1234 mcl::PresentationChain chain(
1235 connection, rpc_id, mock_server,
1236- std::make_shared<mtd::StubClientBufferFactory>(),
1237- std::make_shared<mcl::BufferFactory>());
1238+ factory, mir_buffer_factory);
1239
1240 for (auto i = 0u; i < num_buffers; i++)
1241 chain.allocate_buffer(sizes[i], format, usage, buffer_callback, &buffer[i]);
1242
1243- chain.buffer_available(ipc_buf[1]);
1244- EXPECT_FALSE(buffer[0].buffer_is_set());
1245- EXPECT_TRUE(buffer[1].wait_for_buffer());
1246- EXPECT_FALSE(buffer[2].buffer_is_set());
1247-
1248- chain.buffer_available(ipc_buf[2]);
1249- EXPECT_FALSE(buffer[0].buffer_is_set());
1250- EXPECT_TRUE(buffer[2].wait_for_buffer());
1251-
1252- chain.buffer_available(ipc_buf[0]);
1253- EXPECT_TRUE(buffer[0].wait_for_buffer());
1254+ auto mirbuffer = mir_buffer_factory->generate_buffer(ipc_buf[1]);
1255+ EXPECT_THAT(mirbuffer->client_buffer(), Eq(client_buffers[1]));
1256+ mirbuffer = mir_buffer_factory->generate_buffer(ipc_buf[2]);
1257+ EXPECT_THAT(mirbuffer->client_buffer(), Eq(client_buffers[2]));
1258+ mirbuffer = mir_buffer_factory->generate_buffer(ipc_buf[0]);
1259+ EXPECT_THAT(mirbuffer->client_buffer(), Eq(client_buffers[0]));
1260 }
1261
1262 TEST_F(PresentationChain, frees_buffer_when_asked)
1263@@ -258,18 +256,15 @@
1264 EXPECT_CALL(mock_server, release_buffers(BufferReleaseMatches(release_msg),_,_))
1265 .WillOnce(mtd::RunProtobufClosure());
1266
1267+ auto mir_buffer_factory = std::make_shared<mcl::BufferFactory>();
1268 mcl::PresentationChain chain(
1269 connection, rpc_id, mock_server,
1270 std::make_shared<mtd::StubClientBufferFactory>(),
1271- std::make_shared<mcl::BufferFactory>());
1272+ mir_buffer_factory);
1273
1274 chain.allocate_buffer(size, format, usage, buffer_callback, &buffer);
1275- chain.buffer_available(ipc_buf);
1276- auto b = buffer.wait_for_buffer();
1277- ASSERT_THAT(b, Ne(nullptr));
1278-
1279- chain.release_buffer(b);
1280-
1281+ chain.release_buffer(reinterpret_cast<MirBuffer*>(
1282+ mir_buffer_factory->generate_buffer(ipc_buf).get()));
1283 }
1284
1285 TEST_F(PresentationChain, submits_buffer_when_asked)
1286@@ -284,44 +279,16 @@
1287 EXPECT_CALL(mock_server, submit_buffer(BufferRequestMatches(request),_,_))
1288 .WillOnce(mtd::RunProtobufClosure());
1289
1290+ auto mir_buffer_factory = std::make_shared<mcl::BufferFactory>();
1291 mcl::PresentationChain chain(
1292 connection, rpc_id, mock_server,
1293 std::make_shared<mtd::StubClientBufferFactory>(),
1294- std::make_shared<mcl::BufferFactory>());
1295- chain.allocate_buffer(size, format, usage, buffer_callback, &buffer);
1296- chain.buffer_available(ipc_buf);
1297- auto b = buffer.wait_for_buffer();
1298- ASSERT_THAT(b, Ne(nullptr));
1299-
1300- chain.submit_buffer(b);
1301-}
1302-
1303-TEST_F(PresentationChain, updates_buffer)
1304-{
1305- mtd::MockClientBuffer mock_buffer;
1306- BufferCallbackContext buffer;
1307- mp::BufferRequest request;
1308- request.mutable_id()->set_value(rpc_id);
1309- request.mutable_buffer()->set_buffer_id(buffer_id);
1310-
1311- EXPECT_CALL(mock_server, allocate_buffers(_,_,_))
1312- .WillOnce(mtd::RunProtobufClosure());
1313- EXPECT_CALL(mock_server, submit_buffer(BufferRequestMatches(request),_,_))
1314- .WillOnce(mtd::RunProtobufClosure());
1315- EXPECT_CALL(mock_buffer, update_from(_));
1316- EXPECT_CALL(*factory, create_buffer(_,_,_))
1317- .WillOnce(Return(mir::test::fake_shared(mock_buffer)));
1318-
1319- mcl::PresentationChain chain(
1320- connection, rpc_id, mock_server, factory,
1321- std::make_shared<mcl::BufferFactory>());
1322- chain.allocate_buffer(size, format, usage, buffer_callback, &buffer);
1323- chain.buffer_available(ipc_buf);
1324- auto b = buffer.wait_for_buffer();
1325- ASSERT_THAT(b, Ne(nullptr));
1326-
1327- chain.submit_buffer(b);
1328- chain.buffer_available(ipc_buf);
1329+ mir_buffer_factory);
1330+ chain.allocate_buffer(size, format, usage, buffer_callback, &buffer);
1331+
1332+ auto client_buffer = mir_buffer_factory->generate_buffer(ipc_buf);
1333+ client_buffer->received();
1334+ chain.submit_buffer(reinterpret_cast<MirBuffer*>(client_buffer.get()));
1335 }
1336
1337 TEST_F(PresentationChain, double_submission_throws)
1338@@ -333,43 +300,17 @@
1339 EXPECT_CALL(mock_server, submit_buffer(_,_,_))
1340 .WillOnce(mtd::RunProtobufClosure());
1341
1342+ auto mir_buffer_factory = std::make_shared<mcl::BufferFactory>();
1343 mcl::PresentationChain chain(
1344 connection, rpc_id, mock_server,
1345 std::make_shared<mtd::StubClientBufferFactory>(),
1346- std::make_shared<mcl::BufferFactory>());
1347+ mir_buffer_factory);
1348+
1349 chain.allocate_buffer(size, format, usage, buffer_callback, &buffer);
1350- chain.buffer_available(ipc_buf);
1351- auto b = buffer.wait_for_buffer();
1352- ASSERT_THAT(b, Ne(nullptr));
1353-
1354- chain.submit_buffer(b);
1355+ auto client_buffer = mir_buffer_factory->generate_buffer(ipc_buf);
1356+ client_buffer->received();
1357+ chain.submit_buffer(reinterpret_cast<MirBuffer*>(client_buffer.get()));
1358 EXPECT_THROW({
1359- chain.submit_buffer(b);
1360+ chain.submit_buffer(reinterpret_cast<MirBuffer*>(client_buffer.get()));
1361 }, std::logic_error);
1362 }
1363-
1364-TEST_F(PresentationChain, callback_invoked_when_buffer_returned_from_allocation_and_submission)
1365-{
1366- BufferCount counter;
1367-
1368- EXPECT_CALL(mock_server, allocate_buffers(_,_,_))
1369- .WillOnce(mtd::RunProtobufClosure());
1370- EXPECT_CALL(mock_server, submit_buffer(_,_,_))
1371- .WillOnce(mtd::RunProtobufClosure());
1372-
1373- mcl::PresentationChain chain(
1374- connection, rpc_id, mock_server,
1375- std::make_shared<mtd::StubClientBufferFactory>(),
1376- std::make_shared<mcl::BufferFactory>());
1377- chain.allocate_buffer(size, format, usage, counting_buffer_callback, &counter);
1378- chain.buffer_available(ipc_buf);
1379- std::unique_lock<std::mutex> lk(counter.mut);
1380- EXPECT_TRUE(counter.cv.wait_for(lk, std::chrono::seconds(5), [&] { return counter.buffer; }));
1381- lk.unlock();
1382-
1383- chain.submit_buffer(counter.buffer);
1384- chain.buffer_available(ipc_buf);
1385-
1386- lk.lock();
1387- EXPECT_THAT(counter.count, Eq(2));
1388-}
1389
1390=== modified file 'tests/unit-tests/client/test_protobuf_rpc_channel.cpp'
1391--- tests/unit-tests/client/test_protobuf_rpc_channel.cpp 2016-03-23 06:39:56 +0000
1392+++ tests/unit-tests/client/test_protobuf_rpc_channel.cpp 2016-04-18 17:46:27 +0000
1393@@ -26,13 +26,16 @@
1394 #include "src/client/ping_handler.h"
1395 #include "src/client/buffer_factory.h"
1396
1397+#include "mir/variable_length_array.h"
1398 #include "mir_protobuf.pb.h"
1399 #include "mir_protobuf_wire.pb.h"
1400 #include "mir/input/input_devices.h"
1401
1402 #include "mir/test/doubles/null_client_event_sink.h"
1403 #include "mir/test/doubles/mock_client_buffer_stream.h"
1404+#include "mir/test/doubles/mock_client_buffer.h"
1405 #include "mir/test/fd_utils.h"
1406+#include "mir/test/gmock_fixes.h"
1407
1408 #include <list>
1409 #include <endian.h>
1410@@ -674,3 +677,138 @@
1411 EXPECT_TRUE(second_response_called);
1412 }
1413
1414+struct MockBufferFactory : mcl::AsyncBufferFactory
1415+{
1416+ MOCK_METHOD1(cancel_requests_with_context, void(void*));
1417+ MOCK_METHOD1(generate_buffer, std::unique_ptr<mcl::Buffer>(mir::protobuf::Buffer const&));
1418+ MOCK_METHOD7(expect_buffer, void(
1419+ std::shared_ptr<mcl::ClientBufferFactory> const&,
1420+ MirPresentationChain*,
1421+ mir::geometry::Size, MirPixelFormat, MirBufferUsage,
1422+ mir_buffer_callback, void*));
1423+};
1424+
1425+namespace
1426+{
1427+void buffer_cb(MirPresentationChain*, MirBuffer*, void*)
1428+{
1429+}
1430+
1431+void set_async_buffer_message(
1432+ mir::protobuf::EventSequence& seq,
1433+ MockStreamTransport& transport)
1434+{
1435+ std::vector<uint8_t> send_buffer(static_cast<size_t>(seq.ByteSize()));
1436+ seq.SerializeToArray(send_buffer.data(), send_buffer.size());
1437+ mir::protobuf::wire::Result result;
1438+ result.add_events(send_buffer.data(), send_buffer.size());
1439+ send_buffer.resize(result.ByteSize());
1440+ result.SerializeToArray(send_buffer.data(), send_buffer.size());
1441+
1442+ size_t header_size = 2u;
1443+ std::vector<uint8_t> header(header_size);
1444+ header.data()[0] = static_cast<unsigned char>((result.ByteSize() >> 8) & 0xff);
1445+ header.data()[1] = static_cast<unsigned char>((result.ByteSize() >> 0) & 0xff);
1446+ transport.add_server_message(header);
1447+ transport.add_server_message(send_buffer);
1448+}
1449+
1450+}
1451+TEST_F(MirProtobufRpcChannelTest, creates_buffer_if_not_in_map)
1452+{
1453+ using namespace testing;
1454+ int buffer_id(3);
1455+ auto stream_map = std::make_shared<MockSurfaceMap>();
1456+ auto mock_buffer_factory = std::make_shared<MockBufferFactory>();
1457+ EXPECT_CALL(*mock_buffer_factory, generate_buffer(_))
1458+ .WillOnce(InvokeWithoutArgs([&]{
1459+ return std::make_unique<mcl::Buffer>(
1460+ buffer_cb, nullptr, buffer_id, nullptr, nullptr, mir_buffer_usage_software);
1461+ }));
1462+ EXPECT_CALL(*stream_map, insert(buffer_id, _));
1463+
1464+ auto transport = std::make_unique<NiceMock<MockStreamTransport>>();
1465+ mir::protobuf::EventSequence seq;
1466+ auto request = seq.mutable_buffer_request();
1467+ request->set_operation(mir::protobuf::BufferOperation::add);
1468+ request->mutable_buffer()->set_buffer_id(buffer_id);
1469+ set_async_buffer_message(seq, *transport);
1470+
1471+ mclr::MirProtobufRpcChannel channel{
1472+ std::move(transport),
1473+ stream_map,
1474+ mock_buffer_factory,
1475+ std::make_shared<mcl::DisplayConfiguration>(),
1476+ std::make_shared<mir::input::InputDevices>(),
1477+ std::make_shared<mclr::NullRpcReport>(),
1478+ lifecycle,
1479+ std::make_shared<mir::client::PingHandler>(),
1480+ std::make_shared<mtd::NullClientEventSink>()};
1481+
1482+ channel.on_data_available();
1483+}
1484+
1485+TEST_F(MirProtobufRpcChannelTest, reuses_buffer_if_in_map)
1486+{
1487+ using namespace testing;
1488+ int buffer_id(3);
1489+ auto stream_map = std::make_shared<MockSurfaceMap>();
1490+ auto mock_buffer_factory = std::make_shared<MockBufferFactory>();
1491+ auto mock_client_buffer = std::make_shared<mtd::MockClientBuffer>();
1492+ auto buf = std::make_shared<mcl::Buffer>(buffer_cb, nullptr, buffer_id, mock_client_buffer, nullptr, mir_buffer_usage_software);
1493+ EXPECT_CALL(*stream_map, buffer(buffer_id)).Times(1)
1494+ .WillOnce(Return(buf));
1495+ EXPECT_CALL(*mock_client_buffer, update_from(_))
1496+ .Times(1);
1497+
1498+ auto transport = std::make_unique<NiceMock<MockStreamTransport>>();
1499+ mir::protobuf::EventSequence seq;
1500+ auto request = seq.mutable_buffer_request();
1501+ request->set_operation(mir::protobuf::BufferOperation::update);
1502+ request->mutable_buffer()->set_buffer_id(buffer_id);
1503+ set_async_buffer_message(seq, *transport);
1504+
1505+ mclr::MirProtobufRpcChannel channel{
1506+ std::move(transport),
1507+ stream_map,
1508+ mock_buffer_factory,
1509+ std::make_shared<mcl::DisplayConfiguration>(),
1510+ std::make_shared<mir::input::InputDevices>(),
1511+ std::make_shared<mclr::NullRpcReport>(),
1512+ lifecycle,
1513+ std::make_shared<mir::client::PingHandler>(),
1514+ std::make_shared<mtd::NullClientEventSink>()};
1515+ channel.on_data_available();
1516+}
1517+
1518+TEST_F(MirProtobufRpcChannelTest, sends_incoming_buffer_to_stream_if_stream_id_present)
1519+{
1520+ using namespace testing;
1521+ int buffer_id(3);
1522+ int stream_id = 331;
1523+ auto stream_map = std::make_shared<MockSurfaceMap>();
1524+ auto mock_buffer_factory = std::make_shared<MockBufferFactory>();
1525+ auto mock_client_buffer = std::make_shared<mtd::MockClientBuffer>();
1526+ auto buf = std::make_shared<mcl::Buffer>(buffer_cb, nullptr, buffer_id, mock_client_buffer, nullptr, mir_buffer_usage_software);
1527+ EXPECT_CALL(*stream_map, with_stream_do(mir::frontend::BufferStreamId{stream_id},_))
1528+ .Times(1);
1529+
1530+ auto transport = std::make_unique<NiceMock<MockStreamTransport>>();
1531+ mir::protobuf::EventSequence seq;
1532+ auto request = seq.mutable_buffer_request();
1533+ request->mutable_id()->set_value(stream_id);
1534+ request->mutable_buffer()->set_buffer_id(buffer_id);
1535+ set_async_buffer_message(seq, *transport);
1536+
1537+ mclr::MirProtobufRpcChannel channel{
1538+ std::move(transport),
1539+ stream_map,
1540+ mock_buffer_factory,
1541+ std::make_shared<mcl::DisplayConfiguration>(),
1542+ std::make_shared<mir::input::InputDevices>(),
1543+ std::make_shared<mclr::NullRpcReport>(),
1544+ lifecycle,
1545+ std::make_shared<mir::client::PingHandler>(),
1546+ std::make_shared<mtd::NullClientEventSink>()};
1547+ channel.on_data_available();
1548+}
1549
1550=== modified file 'tests/unit-tests/compositor/test_client_buffers.cpp'
1551--- tests/unit-tests/compositor/test_client_buffers.cpp 2016-04-05 03:47:49 +0000
1552+++ tests/unit-tests/compositor/test_client_buffers.cpp 2016-04-18 17:46:27 +0000
1553@@ -72,7 +72,7 @@
1554 auto stub_buffer = std::make_shared<mtd::StubBuffer>();
1555 EXPECT_CALL(mock_allocator, alloc_buffer(Ref(properties)))
1556 .WillOnce(Return(stub_buffer));
1557- EXPECT_CALL(mock_sink, send_buffer(stream_id, Ref(*stub_buffer), mg::BufferIpcMsgType::full_msg));
1558+ EXPECT_CALL(mock_sink, add_buffer(Ref(*stub_buffer)));
1559 mc::BufferMap map{stream_id, mt::fake_shared(mock_sink), mt::fake_shared(mock_allocator)};
1560 EXPECT_THAT(map.add_buffer(properties), Eq(stub_buffer->id()));
1561 }
1562@@ -108,7 +108,7 @@
1563 ASSERT_THAT(stub_allocator.map, SizeIs(1));
1564 ASSERT_THAT(stub_allocator.ids, SizeIs(1));
1565 auto buffer = map[stub_allocator.ids[0]];
1566- EXPECT_CALL(mock_sink, send_buffer(stream_id, Ref(*buffer), mg::BufferIpcMsgType::update_msg));
1567+ EXPECT_CALL(mock_sink, update_buffer(Ref(*buffer)));
1568 map.send_buffer(stub_allocator.ids[0]);
1569 }
1570
1571@@ -118,8 +118,8 @@
1572 ASSERT_THAT(stub_allocator.map, SizeIs(1));
1573 ASSERT_THAT(stub_allocator.ids, SizeIs(1));
1574 auto buffer = map[stub_allocator.ids[0]];
1575- EXPECT_CALL(mock_sink, send_buffer(stream_id, Ref(*buffer), mg::BufferIpcMsgType::update_msg))
1576- .Times(0);
1577+
1578+ EXPECT_CALL(mock_sink, remove_buffer(Ref(*buffer)));
1579 map.remove_buffer(stub_allocator.ids[0]);
1580 map.send_buffer(stub_allocator.ids[0]);
1581 }
1582@@ -127,9 +127,9 @@
1583 TEST_F(ClientBuffers, can_remove_buffer_from_send_callback)
1584 {
1585 map.add_buffer(properties);
1586- ON_CALL(mock_sink, send_buffer(_,_,_))
1587+ ON_CALL(mock_sink, update_buffer(_))
1588 .WillByDefault(Invoke(
1589- [&] (mf::BufferStreamId, mg::Buffer& buffer, mg::BufferIpcMsgType)
1590+ [&] (mg::Buffer& buffer)
1591 {
1592 map.remove_buffer(buffer.id());
1593 }));
1594@@ -139,7 +139,7 @@
1595
1596 TEST_F(ClientBuffers, ignores_unknown_receive)
1597 {
1598- EXPECT_CALL(mock_sink, send_buffer(_,_,_))
1599+ EXPECT_CALL(mock_sink, add_buffer(_))
1600 .Times(1);
1601 map.add_buffer(properties);
1602 map.remove_buffer(stub_allocator.ids[0]);

Subscribers

People subscribed via source and target branches