Mir

Merge lp:~kdub/mir/send-client-fences-to-server into lp:mir

Proposed by Kevin DuBois
Status: Work in progress
Proposed branch: lp:~kdub/mir/send-client-fences-to-server
Merge into: lp:mir
Diff against target: 903 lines (+428/-259)
11 files modified
src/client/android/client_surface_interpreter.cpp (+2/-3)
src/client/mir_surface.cpp (+13/-0)
src/platform/graphics/android/ipc_operations.cpp (+12/-3)
tests/include/mir_test_doubles/mock_android_alloc_device.h (+11/-50)
tests/mir_test_doubles/mock_android_hw.cpp (+11/-0)
tests/unit-tests/client/android/test_client_surface_interpreter.cpp (+15/-7)
tests/unit-tests/client/test_client_mir_surface.cpp (+125/-5)
tests/unit-tests/graphics/android/CMakeLists.txt (+1/-0)
tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp (+4/-4)
tests/unit-tests/graphics/android/test_ipc_operations.cpp (+192/-0)
tests/unit-tests/graphics/android/test_platform.cpp (+42/-187)
To merge this branch: bzr merge lp:~kdub/mir/send-client-fences-to-server
Reviewer Review Type Date Requested Status
Mir development team Pending
Review via email: mp+241449@code.launchpad.net

Commit message

android: frontend:
send client fences back to the server. This is the complement of lp:~kdub/mir/send-server-fences-to-client. We will start processing the buffer that the client returns at an earlier point. HWC guarantees to wait for the fence before using the buffer, and we ensure that it is waited for in GLES composition in mg::Buffer::bind_to_texture.

Description of the change

android: frontend:
send client fences back to the server. This is the complement of lp:~kdub/mir/send-server-fences-to-client. We will start processing the buffer that the client returns at an earlier point. HWC guarantees to wait for the fence before using the buffer, and we ensure that it is waited for in GLES composition in mg::Buffer::bind_to_texture.

note: I split the ipc functions from test_platform.cpp into test_ipc_operations, as the platform test suite was really testing two objects. I did a bit of cleanup of the test in this area too.

currently testing with the full stack.

To post a comment you must log in.

Unmerged revisions

2007. By Kevin DuBois

merge in mir

2006. By Kevin DuBois

further test cleanups

2005. By Kevin DuBois

merge in mir

2004. By Kevin DuBois

some test cleanups

2003. By Kevin DuBois

adjust for loop spacings

2002. By Kevin DuBois

merge mir

2001. By Kevin DuBois

merge in base

2000. By Kevin DuBois

merge in lp:mir

1999. By Kevin DuBois

correct problematic mirsurface test

1998. By Kevin DuBois

merge base

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/client/android/client_surface_interpreter.cpp'
2--- src/client/android/client_surface_interpreter.cpp 2014-10-01 06:25:56 +0000
3+++ src/client/android/client_surface_interpreter.cpp 2014-11-11 18:48:42 +0000
4@@ -45,9 +45,8 @@
5
6 void mcla::ClientSurfaceInterpreter::driver_returns_buffer(ANativeWindowBuffer*, int fence_fd)
7 {
8- //TODO: pass fence to server instead of waiting here
9- mga::SyncFence sync_fence(sync_ops, mir::Fd(fence_fd));
10- sync_fence.wait();
11+ auto buffer = surface.get_current_buffer()->native_buffer_handle();
12+ buffer->update_usage(fence_fd, mga::BufferAccess::write);
13
14 surface.request_and_wait_for_next_buffer();
15 }
16
17=== modified file 'src/client/mir_surface.cpp'
18--- src/client/mir_surface.cpp 2014-11-11 15:50:11 +0000
19+++ src/client/mir_surface.cpp 2014-11-11 18:48:42 +0000
20@@ -208,6 +208,15 @@
21 //TODO: we have extract the per-message information from the buffer
22 *buffer_request.mutable_id() = surface.id();
23 buffer_request.mutable_buffer()->set_buffer_id(surface.buffer().buffer_id());
24+
25+ MirNativeBuffer update_msg;
26+ memset(&update_msg, 0, sizeof(update_msg));
27+ auto client_buffer = buffer_depository->current_buffer();
28+ client_buffer->fill_update_msg(update_msg);
29+ for (auto i = 0; i < update_msg.data_items; i++)
30+ buffer_request.mutable_buffer()->add_data(update_msg.fd[i]);
31+ for (auto i = 0; i < update_msg.fd_items; i++)
32+ buffer_request.mutable_buffer()->add_fd(update_msg.fd[i]);
33 perf_report->end_frame(surface.buffer().buffer_id());
34 lock.unlock();
35
36@@ -302,6 +311,10 @@
37 {
38 {
39 std::lock_guard<decltype(mutex)> lock(mutex);
40+ for (auto fd : buffer_request.buffer().fd())
41+ ::close(fd);
42+ buffer_request.mutable_buffer()->clear_fd();
43+ buffer_request.mutable_buffer()->clear_data();
44 process_incoming_buffer();
45 }
46
47
48=== modified file 'src/platform/graphics/android/ipc_operations.cpp'
49--- src/platform/graphics/android/ipc_operations.cpp 2014-10-16 19:07:47 +0000
50+++ src/platform/graphics/android/ipc_operations.cpp 2014-11-11 18:48:42 +0000
51@@ -45,11 +45,11 @@
52 auto buffer_handle = native_buffer->handle();
53 int offset = 0;
54
55- for(auto i = 0; i < buffer_handle->numFds; i++)
56+ for (auto i = 0; i < buffer_handle->numFds; i++)
57 {
58 msg.pack_fd(mir::Fd(IntOwnedFd{buffer_handle->data[offset++]}));
59 }
60- for(auto i = 0; i < buffer_handle->numInts; i++)
61+ for (auto i = 0; i < buffer_handle->numInts; i++)
62 {
63 msg.pack_data(buffer_handle->data[offset++]);
64 }
65@@ -59,8 +59,17 @@
66 }
67 }
68
69-void mga::IpcOperations::unpack_buffer(BufferIpcMessage&, Buffer const&) const
70+void mga::IpcOperations::unpack_buffer(BufferIpcMessage& msg, Buffer const& buffer) const
71 {
72+ auto const& fds = msg.fds();
73+ auto const& data = msg.data();
74+ auto native_buffer = buffer.native_buffer_handle();
75+ if ((data.size() >= 1) && (fds.size() >= 1) &&
76+ (data[0] == static_cast<int>(mga::BufferFlag::fenced)))
77+ {
78+ int fence = fds[0];
79+ native_buffer->update_usage(fence, mga::BufferAccess::write);
80+ }
81 }
82
83 std::shared_ptr<mg::PlatformIPCPackage> mga::IpcOperations::connection_ipc_package()
84
85=== modified file 'tests/include/mir_test_doubles/mock_android_alloc_device.h'
86--- tests/include/mir_test_doubles/mock_android_alloc_device.h 2013-06-18 08:00:49 +0000
87+++ tests/include/mir_test_doubles/mock_android_alloc_device.h 2014-11-11 18:48:42 +0000
88@@ -18,6 +18,7 @@
89 #ifndef MIR_TEST_DOUBLES_MOCK_ANDROID_ALLOC_DEVICE_H_
90 #define MIR_TEST_DOUBLES_MOCK_ANDROID_ALLOC_DEVICE_H_
91
92+#include <memory>
93 #include <gmock/gmock.h>
94 #include <hardware/gralloc.h>
95
96@@ -25,49 +26,27 @@
97 {
98 namespace test
99 {
100-namespace android
101-{
102-class ICSAllocInterface
103-{
104-public:
105- virtual ~ICSAllocInterface() {/* TODO: make nothrow */}
106- virtual int alloc_interface(alloc_device_t* dev, int w, int h,
107- int format, int usage, buffer_handle_t* handle, int* stride) = 0;
108- virtual int free_interface(alloc_device_t* dev, buffer_handle_t handle) = 0;
109- virtual int dump_interface(alloc_device_t* dev, char *buf, int len) = 0;
110-
111-};
112-}
113 namespace doubles
114 {
115-class MockAllocDevice : public android::ICSAllocInterface,
116- public alloc_device_t
117+std::shared_ptr<native_handle_t> generate_native_handle(size_t num_ints, size_t num_fds);
118+struct MockAllocDevice : alloc_device_t
119 {
120-public:
121-
122- MockAllocDevice()
123+ MockAllocDevice() :
124+ buffer_handle{generate_native_handle(43, 22)},
125+ fake_stride{300}
126 {
127 using namespace testing;
128-
129- buffer_handle = mock_generate_sane_android_handle(43, 22);
130- fake_stride = 300;
131-
132 alloc = hook_alloc;
133 free = hook_free;
134 dump = hook_dump;
135 ON_CALL(*this, alloc_interface(_,_,_,_,_,_,_))
136- .WillByDefault(DoAll(
137- SetArgPointee<5>(buffer_handle),
138+ .WillByDefault(DoAll(
139+ SetArgPointee<5>(buffer_handle.get()),
140 SetArgPointee<6>(fake_stride),
141 Return(0)));
142 ON_CALL(*this, free_interface(_,_))
143- .WillByDefault(Return(0));
144-
145- }
146-
147- ~MockAllocDevice()
148- {
149- ::free((void*)buffer_handle);
150+ .WillByDefault(Return(0));
151+
152 }
153
154 static int hook_alloc(alloc_device_t* mock_alloc,
155@@ -90,29 +69,11 @@
156 mocker->dump_interface(mock_alloc, buf, buf_len);
157 }
158
159- native_handle_t* mock_generate_sane_android_handle(int numFd, int numInt)
160- {
161- native_handle_t *handle;
162- int total=numFd + numInt;
163- int header_offset=3;
164-
165- handle = (native_handle_t*) malloc(sizeof(int) * (header_offset+ total));
166- handle->version = 0x389;
167- handle->numFds = numFd;
168- handle->numInts = numInt;
169- for(int i=0; i<total; i++)
170- {
171- handle->data[i] = i*3;
172- }
173-
174- return handle;
175- }
176-
177 MOCK_METHOD7(alloc_interface, int(alloc_device_t*, int, int, int, int, buffer_handle_t*, int*));
178 MOCK_METHOD2(free_interface, int(alloc_device_t*, buffer_handle_t));
179 MOCK_METHOD3(dump_interface, int(alloc_device_t*, char*, int));
180
181- native_handle_t* buffer_handle;
182+ std::shared_ptr<native_handle_t> const buffer_handle;
183 unsigned int fake_stride;
184 };
185 }
186
187=== modified file 'tests/mir_test_doubles/mock_android_hw.cpp'
188--- tests/mir_test_doubles/mock_android_hw.cpp 2014-03-06 06:05:17 +0000
189+++ tests/mir_test_doubles/mock_android_hw.cpp 2014-11-11 18:48:42 +0000
190@@ -111,3 +111,14 @@
191 int rc = global_mock_android_hw->hw_get_module(id, module);
192 return rc;
193 }
194+
195+std::shared_ptr<native_handle_t> mtd::generate_native_handle(size_t num_ints, size_t num_fds)
196+{
197+ auto handle_size = sizeof(native_handle_t) + (sizeof(int)*(num_ints + num_fds));
198+ auto native_buffer_handle = std::shared_ptr<native_handle_t>(reinterpret_cast<native_handle_t*>(::operator new(handle_size)));
199+ native_buffer_handle->numInts = num_ints;
200+ native_buffer_handle->numFds = num_fds;
201+ for (auto i = 0u; i < (num_ints+num_fds); i++)
202+ native_buffer_handle->data[i] = i;
203+ return native_buffer_handle;
204+}
205
206=== modified file 'tests/unit-tests/client/android/test_client_surface_interpreter.cpp'
207--- tests/unit-tests/client/android/test_client_surface_interpreter.cpp 2014-10-27 20:20:10 +0000
208+++ tests/unit-tests/client/android/test_client_surface_interpreter.cpp 2014-11-11 18:48:42 +0000
209@@ -22,6 +22,7 @@
210 #include "src/client/client_buffer.h"
211 #include "src/client/android/client_surface_interpreter.h"
212 #include "mir_test_doubles/stub_android_native_buffer.h"
213+#include "mir_test_doubles/mock_android_native_buffer.h"
214 #include "mir_test/fake_shared.h"
215 #include <system/window.h>
216 #include <gmock/gmock.h>
217@@ -131,18 +132,25 @@
218 EXPECT_EQ(buffer.get(), returned_buffer);
219 }
220
221-TEST_F(AndroidInterpreter, advances_surface_on_buffer_return)
222+TEST_F(AndroidInterpreter, updates_fence_and_advances_surface_on_buffer_plus_fence_return)
223 {
224 using namespace testing;
225- ANativeWindowBuffer buffer;
226-
227+ int fake_fence{45};
228+ auto buffer = std::make_shared<NiceMock<mtd::MockAndroidNativeBuffer>>();
229 testing::NiceMock<MockMirSurface> mock_surface{surf_params};
230- mcla::ClientSurfaceInterpreter interpreter(mock_surface);
231
232- EXPECT_CALL(mock_surface, request_and_wait_for_next_buffer())
233+ EXPECT_CALL(*mock_client_buffer, native_buffer_handle())
234+ .Times(1)
235+ .WillOnce(Return(buffer));
236+ EXPECT_CALL(*buffer, update_usage(fake_fence, mga::BufferAccess::write))
237 .Times(1);
238-
239- interpreter.driver_returns_buffer(&buffer, -1);
240+ EXPECT_CALL(mock_surface, get_current_buffer())
241+ .Times(1)
242+ .WillOnce(Return(mock_client_buffer));
243+
244+ mcla::ClientSurfaceInterpreter interpreter(mock_surface);
245+
246+ interpreter.driver_returns_buffer(buffer->anwb(), fake_fence);
247 }
248
249 /* format is an int that is set by the driver. these are not the HAL_PIXEL_FORMATS in android */
250
251=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
252--- tests/unit-tests/client/test_client_mir_surface.cpp 2014-10-28 13:59:51 +0000
253+++ tests/unit-tests/client/test_client_mir_surface.cpp 2014-11-11 18:48:42 +0000
254@@ -31,6 +31,7 @@
255 #include "mir/input/input_platform.h"
256 #include "mir/input/input_receiver_thread.h"
257
258+#include "mir_test_doubles/fd_matcher.h"
259 #include "mir_test/test_protobuf_server.h"
260 #include "mir_test/stub_server_tool.h"
261 #include "mir_test/gmock_fixes.h"
262@@ -49,7 +50,7 @@
263 namespace mg = mir::graphics;
264 namespace geom = mir::geometry;
265 namespace mt = mir::test;
266-
267+namespace mtd = mir::test::doubles;
268 namespace
269 {
270
271@@ -538,10 +539,28 @@
272 {
273 using namespace testing;
274
275- FakeRpcChannel fake_channel;
276- mir::protobuf::DisplayServer::Stub unresponsive_server{&fake_channel};
277-
278- auto const surface = create_surface_with(unresponsive_server, stub_buffer_factory);
279+ struct UnresponsiveExchangeServer : public mir::protobuf::DisplayServer::Stub
280+ {
281+ UnresponsiveExchangeServer(::google::protobuf::RpcChannel* fake_channel) :
282+ mir::protobuf::DisplayServer::Stub{fake_channel}
283+ {
284+ }
285+
286+ void exchange_buffer(
287+ ::google::protobuf::RpcController*,
288+ const ::mir::protobuf::BufferRequest*,
289+ ::mir::protobuf::Buffer*,
290+ ::google::protobuf::Closure*) override
291+ {
292+ }
293+ };
294+
295+ TestConnectionConfiguration conf;
296+ connection = std::make_shared<MirConnection>(conf);
297+ connection->connect("MirClientSurfaceTest", null_connected_callback, 0)->wait_for_all();
298+ UnresponsiveExchangeServer unresponsive_server{conf.the_rpc_channel().get()};
299+
300+ auto const surface = create_and_wait_for_surface_with(unresponsive_server, stub_buffer_factory);
301
302 auto buffer_wait_handle = surface->next_buffer(&null_surface_callback, nullptr);
303
304@@ -759,3 +778,104 @@
305
306 EXPECT_GE(std::chrono::steady_clock::now(), expected_end);
307 }
308+
309+struct FdGeneratingBuffer : public mcl::ClientBuffer
310+{
311+ FdGeneratingBuffer(mir::Fd fd) :
312+ fd{std::move(fd)}
313+ {
314+ }
315+ std::shared_ptr<mcl::MemoryRegion> secure_for_cpu_write()
316+ {
317+ return std::shared_ptr<mcl::MemoryRegion>();
318+ }
319+ geom::Size size() const { return size_; }
320+ geom::Stride stride() const { return geom::Stride{0};}
321+ MirPixelFormat pixel_format() const { return pf_; }
322+ uint32_t age() const { return 0; }
323+ void increment_age() {}
324+ void mark_as_submitted() {}
325+ std::shared_ptr<mg::NativeBuffer> native_buffer_handle() const
326+ {
327+ return std::shared_ptr<mg::NativeBuffer>();
328+ }
329+ void update_from(MirBufferPackage const&) {}
330+ void fill_update_msg(MirBufferPackage& package)
331+ {
332+ package.data_items = 0;
333+ package.fd_items = 1;
334+ package.fd[0] = dup(fd);
335+ }
336+private:
337+ mir::Fd const fd;
338+ geom::Size size_;
339+ MirPixelFormat pf_;
340+};
341+
342+struct StubFdBufferFactory : public mcl::ClientBufferFactory
343+{
344+ StubFdBufferFactory(mir::Fd fd) :
345+ fd{std::move(fd)}
346+ {
347+ }
348+
349+ std::shared_ptr<mcl::ClientBuffer> create_buffer(
350+ std::shared_ptr<MirBufferPackage> const&,
351+ geom::Size, MirPixelFormat)
352+ {
353+ return std::make_shared<FdGeneratingBuffer>(fd);
354+ }
355+ mir::Fd const fd;
356+};
357+
358+struct ExchangeMonitoringRpcServer : mir::protobuf::DisplayServer::Stub
359+{
360+ ExchangeMonitoringRpcServer(::google::protobuf::RpcChannel* fake_channel) :
361+ mir::protobuf::DisplayServer::Stub{fake_channel}
362+ {
363+ }
364+
365+ virtual void exchange_buffer(
366+ ::google::protobuf::RpcController*,
367+ const ::mir::protobuf::BufferRequest* request,
368+ ::mir::protobuf::Buffer*,
369+ ::google::protobuf::Closure* closure) override
370+ {
371+ last_exchange_buffer_request = *request;
372+ last_exchange_buffer_closure = closure;
373+ }
374+
375+ void complete_exchange_buffer()
376+ {
377+ if (last_exchange_buffer_closure)
378+ last_exchange_buffer_closure->Run();
379+ }
380+ ::mir::protobuf::BufferRequest last_exchange_buffer_request;
381+ ::google::protobuf::Closure* last_exchange_buffer_closure;
382+};
383+
384+TEST_F(MirClientSurfaceTest, sends_fd_that_the_buffer_provides_and_closes_after_call_completes)
385+{
386+ using namespace testing;
387+ mir::Fd fd{fileno(tmpfile())};
388+ auto stub_fd_buffer_factory = std::make_shared<StubFdBufferFactory>(fd);
389+
390+ mir::protobuf::ConnectParameters connect_parameters;
391+ connect_parameters.set_application_name("test");
392+
393+ TestConnectionConfiguration conf;
394+ connection = std::make_shared<MirConnection>(conf);
395+ MirWaitHandle* wait_handle = connection->connect("MirClientSurfaceTest",
396+ null_connected_callback, 0);
397+ wait_handle->wait_for_all();
398+ ExchangeMonitoringRpcServer server(conf.the_rpc_channel().get());
399+ auto const surface = create_and_wait_for_surface_with(server, stub_fd_buffer_factory);
400+
401+ auto buffer_wait_handle = surface->next_buffer(&null_surface_callback, nullptr);
402+ auto& buffer_request = server.last_exchange_buffer_request.buffer();
403+ ASSERT_THAT(buffer_request.fd().size(), (Eq(1)));
404+ EXPECT_THAT(buffer_request.fd(0), mtd::RawFdIsValid());
405+ server.complete_exchange_buffer();
406+ buffer_wait_handle->wait_for_all();
407+ EXPECT_THAT(buffer_request.fd(0), Not(mtd::RawFdIsValid()));
408+}
409
410=== modified file 'tests/unit-tests/graphics/android/CMakeLists.txt'
411--- tests/unit-tests/graphics/android/CMakeLists.txt 2014-10-01 06:25:56 +0000
412+++ tests/unit-tests/graphics/android/CMakeLists.txt 2014-11-11 18:48:42 +0000
413@@ -28,6 +28,7 @@
414 ${CMAKE_CURRENT_SOURCE_DIR}/test_device_detection.cpp
415 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_wrapper.cpp
416 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_fallback_gl_renderer.cpp
417+ ${CMAKE_CURRENT_SOURCE_DIR}/test_ipc_operations.cpp
418 $<TARGET_OBJECTS:mirplatformgraphicsandroidobjects>
419 )
420
421
422=== modified file 'tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp'
423--- tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp 2014-03-06 06:05:17 +0000
424+++ tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp 2014-11-11 18:48:42 +0000
425@@ -69,7 +69,7 @@
426 using namespace testing;
427 EXPECT_CALL(*mock_alloc_device, alloc_interface(_,_,_,_,_,_,_))
428 .WillOnce(DoAll(
429- SetArgPointee<5>(mock_alloc_device->buffer_handle),
430+ SetArgPointee<5>(mock_alloc_device->buffer_handle.get()),
431 SetArgPointee<6>(size.width.as_uint32_t()*4),
432 Return(-1)));
433
434@@ -83,7 +83,7 @@
435 using namespace testing;
436 EXPECT_CALL(*mock_alloc_device, alloc_interface(_,_,_,_,_,_,_))
437 .WillOnce(DoAll(
438- SetArgPointee<5>(mock_alloc_device->buffer_handle),
439+ SetArgPointee<5>(mock_alloc_device->buffer_handle.get()),
440 SetArgPointee<6>(0),
441 Return(0)));
442
443@@ -122,10 +122,10 @@
444
445 EXPECT_CALL(*mock_alloc_device, alloc_interface(_,_,_,_,_,_,_))
446 .WillOnce(DoAll(
447- SetArgPointee<5>(mock_alloc_device->buffer_handle),
448+ SetArgPointee<5>(mock_alloc_device->buffer_handle.get()),
449 SetArgPointee<6>(size.width.as_uint32_t()*4),
450 Return(0)));
451- EXPECT_CALL(*mock_alloc_device, free_interface(_,mock_alloc_device->buffer_handle));
452+ EXPECT_CALL(*mock_alloc_device, free_interface(_,mock_alloc_device->buffer_handle.get()));
453
454 alloc_adaptor->alloc_buffer(size, pf, usage);
455 }
456
457=== added file 'tests/unit-tests/graphics/android/test_ipc_operations.cpp'
458--- tests/unit-tests/graphics/android/test_ipc_operations.cpp 1970-01-01 00:00:00 +0000
459+++ tests/unit-tests/graphics/android/test_ipc_operations.cpp 2014-11-11 18:48:42 +0000
460@@ -0,0 +1,192 @@
461+/*
462+
463+ * Copyright © 2012-2014 Canonical Ltd.
464+ *
465+ * This program is free software: you can redistribute it and/or modify
466+ * it under the terms of the GNU General Public License version 3 as
467+ * published by the Free Software Foundation.
468+ *
469+ * This program is distributed in the hope that it will be useful,
470+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
471+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
472+ * GNU General Public License for more details.
473+ *
474+ * You should have received a copy of the GNU General Public License
475+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
476+ *
477+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
478+ */
479+
480+#include "src/server/report/null_report_factory.h"
481+#include "mir/graphics/native_platform.h"
482+#include "mir/graphics/platform_ipc_operations.h"
483+#include "mir/options/program_option.h"
484+#include "src/platform/graphics/android/platform.h"
485+#include "src/platform/graphics/android/ipc_operations.h"
486+#include "mir_test_doubles/mock_buffer.h"
487+#include "mir_test_doubles/mock_android_hw.h"
488+#include "mir_test_doubles/mock_buffer_ipc_message.h"
489+#include "mir_test_doubles/mock_display_report.h"
490+#include "mir_test_doubles/stub_display_builder.h"
491+#include "mir_test_doubles/mock_android_native_buffer.h"
492+#include "mir_test_doubles/stub_android_native_buffer.h"
493+#include "mir_test_doubles/fd_matcher.h"
494+#include "mir_test/fake_shared.h"
495+#include "mir_test_doubles/mock_android_native_buffer.h"
496+#include "mir_test_doubles/mock_android_alloc_device.h"
497+#include <gtest/gtest.h>
498+
499+namespace mg=mir::graphics;
500+namespace mga=mir::graphics::android;
501+namespace mt=mir::test;
502+namespace mtd=mir::test::doubles;
503+namespace mr=mir::report;
504+namespace geom=mir::geometry;
505+namespace mo=mir::options;
506+
507+struct IpcOperations : testing::Test
508+{
509+ IpcOperations() :
510+ stride{300*4},
511+ num_ints{30},
512+ num_fds{12},
513+ native_buffer{std::make_shared<mtd::MockAndroidNativeBuffer>()},
514+ native_buffer_handle{mtd::generate_native_handle(num_ints, num_fds)},
515+ mock_buffer{std::make_shared<testing::NiceMock<mtd::MockBuffer>>()}
516+ {
517+ using namespace testing;
518+ ON_CALL(*native_buffer, handle())
519+ .WillByDefault(Return(native_buffer_handle.get()));
520+ ON_CALL(*mock_buffer, native_buffer_handle())
521+ .WillByDefault(Return(native_buffer));
522+ ON_CALL(*mock_buffer, stride())
523+ .WillByDefault(Return(stride));
524+ }
525+
526+ geom::Stride stride;
527+ size_t num_ints;
528+ size_t num_fds;
529+ std::shared_ptr<mtd::MockAndroidNativeBuffer> native_buffer;
530+ std::shared_ptr<native_handle_t> native_buffer_handle;
531+ std::shared_ptr<mtd::MockBuffer> mock_buffer;
532+ std::shared_ptr<mg::DisplayReport> stub_display_report;
533+ mga::IpcOperations ipc_operations;
534+};
535+
536+/* ipc packaging tests */
537+TEST_F(IpcOperations, test_ipc_data_packed_correctly_for_full_ipc_with_fence)
538+{
539+ using namespace ::testing;
540+ int fake_fence{333};
541+ EXPECT_CALL(*native_buffer, copy_fence())
542+ .WillOnce(Return(fake_fence));
543+
544+ mtd::MockBufferIpcMessage mock_ipc_msg;
545+ int offset = 0;
546+ EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::fenced)));
547+ EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(fake_fence)));
548+ for (auto i = 0u; i < num_fds; i++)
549+ EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(native_buffer_handle->data[offset++])));
550+ for (auto i = 0u; i < num_ints; i++)
551+ EXPECT_CALL(mock_ipc_msg, pack_data(native_buffer_handle->data[offset++]));
552+
553+ EXPECT_CALL(*mock_buffer, stride())
554+ .WillOnce(Return(stride));
555+ EXPECT_CALL(mock_ipc_msg, pack_stride(stride))
556+ .Times(1);
557+
558+ EXPECT_CALL(*mock_buffer, size())
559+ .WillOnce(Return(mir::geometry::Size{123, 456}));
560+ EXPECT_CALL(mock_ipc_msg, pack_size(_))
561+ .Times(1);
562+
563+ ipc_operations.pack_buffer(mock_ipc_msg, *mock_buffer, mg::BufferIpcMsgType::full_msg);
564+}
565+
566+TEST_F(IpcOperations, test_ipc_data_packed_correctly_for_full_ipc_without_fence)
567+{
568+ using namespace ::testing;
569+ EXPECT_CALL(*native_buffer, copy_fence())
570+ .WillOnce(Return(-1));
571+
572+ mtd::MockBufferIpcMessage mock_ipc_msg;
573+ int offset = 0;
574+ EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::unfenced)));
575+ EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(-1)))
576+ .Times(0);
577+
578+ for (auto i = 0u; i < num_fds; i++)
579+ {
580+ EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(native_buffer_handle->data[offset++])))
581+ .Times(1);
582+ }
583+ for (auto i = 0u; i < num_ints; i++)
584+ {
585+ EXPECT_CALL(mock_ipc_msg, pack_data(native_buffer_handle->data[offset++]))
586+ .Times(1);
587+ }
588+
589+ EXPECT_CALL(*mock_buffer, stride())
590+ .WillOnce(Return(stride));
591+ EXPECT_CALL(mock_ipc_msg, pack_stride(stride))
592+ .Times(1);
593+
594+ EXPECT_CALL(*mock_buffer, size())
595+ .WillOnce(Return(mir::geometry::Size{123, 456}));
596+ EXPECT_CALL(mock_ipc_msg, pack_size(_))
597+ .Times(1);
598+
599+ ipc_operations.pack_buffer(mock_ipc_msg, *mock_buffer, mg::BufferIpcMsgType::full_msg);
600+}
601+
602+TEST_F(IpcOperations, test_ipc_data_packed_correctly_for_partial_ipc)
603+{
604+ using namespace ::testing;
605+
606+ int fake_fence{33};
607+ mtd::MockBufferIpcMessage mock_ipc_msg;
608+
609+ Sequence seq;
610+ EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::fenced)))
611+ .InSequence(seq);
612+ EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(fake_fence)))
613+ .InSequence(seq);
614+ EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::unfenced)))
615+ .InSequence(seq);
616+
617+ EXPECT_CALL(*native_buffer, copy_fence())
618+ .Times(2)
619+ .WillOnce(Return(fake_fence))
620+ .WillOnce(Return(-1));
621+
622+ ipc_operations.pack_buffer(mock_ipc_msg, *mock_buffer, mg::BufferIpcMsgType::update_msg);
623+ ipc_operations.pack_buffer(mock_ipc_msg, *mock_buffer, mg::BufferIpcMsgType::update_msg);
624+}
625+
626+TEST_F(IpcOperations, unpacks_fenced_buffer_update)
627+{
628+ using namespace ::testing;
629+ mtd::MockBufferIpcMessage mock_ipc_msg;
630+ mir::Fd stub_fd{fileno(tmpfile())};
631+
632+ EXPECT_CALL(mock_ipc_msg, data())
633+ .WillOnce(Return(std::vector<int>{static_cast<int>(mga::BufferFlag::fenced)}));
634+ EXPECT_CALL(mock_ipc_msg, fds())
635+ .WillOnce(Return(std::vector<mir::Fd>{stub_fd}));
636+ EXPECT_CALL(*native_buffer, update_usage(_, mga::BufferAccess::write))
637+ .Times(1);
638+ ipc_operations.unpack_buffer(mock_ipc_msg, *mock_buffer);
639+}
640+
641+TEST_F(IpcOperations, unpacks_unfenced_buffer)
642+{
643+ using namespace ::testing;
644+ mtd::MockBufferIpcMessage mock_ipc_msg;
645+ EXPECT_CALL(mock_ipc_msg, data())
646+ .WillOnce(Return(std::vector<int>{static_cast<int>(mga::BufferFlag::unfenced)}));
647+ EXPECT_CALL(mock_ipc_msg, fds())
648+ .WillOnce(Return(std::vector<mir::Fd>{}));
649+ EXPECT_CALL(*native_buffer, update_usage(_, _))
650+ .Times(0);
651+ ipc_operations.unpack_buffer(mock_ipc_msg, *mock_buffer);
652+}
653
654=== modified file 'tests/unit-tests/graphics/android/test_platform.cpp'
655--- tests/unit-tests/graphics/android/test_platform.cpp 2014-10-27 19:49:37 +0000
656+++ tests/unit-tests/graphics/android/test_platform.cpp 2014-11-11 18:48:42 +0000
657@@ -17,19 +17,16 @@
658 */
659
660 #include "src/server/report/null_report_factory.h"
661-#include "mir/graphics/native_platform.h"
662-#include "mir/graphics/platform_ipc_operations.h"
663-#include "mir/options/program_option.h"
664+#include "mir_test_doubles/mock_display_report.h"
665 #include "src/platform/graphics/android/platform.h"
666-#include "mir_test_doubles/mock_buffer.h"
667+#include "mir_test_doubles/mock_buffer_ipc_message.h"
668 #include "mir_test_doubles/mock_android_hw.h"
669-#include "mir_test_doubles/mock_buffer_ipc_message.h"
670-#include "mir_test_doubles/mock_display_report.h"
671+#include "mir_test_doubles/fd_matcher.h"
672 #include "mir_test_doubles/stub_display_builder.h"
673-#include "mir_test_doubles/fd_matcher.h"
674+#include "mir_test_doubles/mock_android_native_buffer.h"
675+#include "mir_test_doubles/mock_buffer.h"
676+#include "mir_test_doubles/mock_android_alloc_device.h"
677 #include "mir_test/fake_shared.h"
678-#include "mir_test_doubles/mock_android_native_buffer.h"
679-#include <system/window.h>
680 #include <gtest/gtest.h>
681
682 namespace mg=mir::graphics;
683@@ -38,184 +35,42 @@
684 namespace mtd=mir::test::doubles;
685 namespace mr=mir::report;
686 namespace geom=mir::geometry;
687-namespace mo=mir::options;
688-
689-class PlatformBufferIPCPackaging : public ::testing::Test
690-{
691-protected:
692- virtual void SetUp()
693- {
694- using namespace testing;
695-
696- stub_display_builder = std::make_shared<mtd::StubDisplayBuilder>();
697- stub_display_report = mr::null_display_report();
698- stride = geom::Stride(300*4);
699-
700- num_ints = 43;
701- num_fds = 55;
702- auto handle_size = sizeof(native_handle_t) + (sizeof(int)*(num_ints + num_fds));
703- auto native_buffer_raw = (native_handle_t*) ::operator new(handle_size);
704- native_buffer_handle = std::shared_ptr<native_handle_t>(native_buffer_raw);
705-
706- native_buffer_handle->numInts = num_ints;
707- native_buffer_handle->numFds = num_fds;
708- for (auto i = 0u; i < (num_ints+num_fds); i++)
709- {
710- native_buffer_handle->data[i] = i;
711- }
712-
713- native_buffer = std::make_shared<mtd::MockAndroidNativeBuffer>();
714- mock_buffer = std::make_shared<NiceMock<mtd::MockBuffer>>();
715-
716- ON_CALL(*native_buffer, handle())
717- .WillByDefault(Return(native_buffer_handle.get()));
718- ON_CALL(*mock_buffer, native_buffer_handle())
719- .WillByDefault(Return(native_buffer));
720- ON_CALL(*mock_buffer, stride())
721- .WillByDefault(Return(stride));
722- }
723-
724- std::shared_ptr<mtd::MockAndroidNativeBuffer> native_buffer;
725- std::shared_ptr<mtd::StubDisplayBuilder> stub_display_builder;
726- std::shared_ptr<mtd::MockBuffer> mock_buffer;
727- std::shared_ptr<native_handle_t> native_buffer_handle;
728- std::shared_ptr<mg::DisplayReport> stub_display_report;
729- geom::Stride stride;
730- unsigned int num_ints, num_fds;
731-};
732-
733-/* ipc packaging tests */
734-TEST_F(PlatformBufferIPCPackaging, test_ipc_data_packed_correctly_for_full_ipc_with_fence)
735-{
736- using namespace ::testing;
737- int fake_fence{333};
738- EXPECT_CALL(*native_buffer, copy_fence())
739- .WillOnce(Return(fake_fence));
740-
741- mga::Platform platform(stub_display_builder, stub_display_report);
742-
743- mtd::MockBufferIpcMessage mock_ipc_msg;
744- int offset = 0;
745- EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::fenced)));
746- EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(fake_fence)));
747- for (auto i = 0u; i < num_fds; i++)
748- EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(native_buffer_handle->data[offset++])));
749- for (auto i = 0u; i < num_ints; i++)
750- EXPECT_CALL(mock_ipc_msg, pack_data(native_buffer_handle->data[offset++]));
751-
752- EXPECT_CALL(*mock_buffer, stride())
753- .WillOnce(Return(stride));
754- EXPECT_CALL(mock_ipc_msg, pack_stride(stride))
755- .Times(1);
756-
757- EXPECT_CALL(*mock_buffer, size())
758- .WillOnce(Return(mir::geometry::Size{123, 456}));
759- EXPECT_CALL(mock_ipc_msg, pack_size(_))
760- .Times(1);
761-
762- platform.fill_buffer_package(
763- &mock_ipc_msg, mock_buffer.get(), mg::BufferIpcMsgType::full_msg);
764-}
765-
766-TEST_F(PlatformBufferIPCPackaging, test_ipc_data_packed_correctly_for_full_ipc_without_fence)
767-{
768- using namespace ::testing;
769- EXPECT_CALL(*native_buffer, copy_fence())
770- .WillOnce(Return(-1));
771-
772- mga::Platform platform(stub_display_builder, stub_display_report);
773-
774- mtd::MockBufferIpcMessage mock_ipc_msg;
775- int offset = 0;
776- EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::unfenced)));
777- EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(-1)))
778- .Times(0);
779-
780- for (auto i = 0u; i < num_fds; i++)
781- {
782- EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(native_buffer_handle->data[offset++])))
783- .Times(1);
784- }
785- for (auto i = 0u; i < num_ints; i++)
786- {
787- EXPECT_CALL(mock_ipc_msg, pack_data(native_buffer_handle->data[offset++]))
788- .Times(1);
789- }
790-
791- EXPECT_CALL(*mock_buffer, stride())
792- .WillOnce(Return(stride));
793- EXPECT_CALL(mock_ipc_msg, pack_stride(stride))
794- .Times(1);
795-
796- EXPECT_CALL(*mock_buffer, size())
797- .WillOnce(Return(mir::geometry::Size{123, 456}));
798- EXPECT_CALL(mock_ipc_msg, pack_size(_))
799- .Times(1);
800-
801- platform.fill_buffer_package(
802- &mock_ipc_msg, mock_buffer.get(), mg::BufferIpcMsgType::full_msg);
803-}
804-
805-TEST_F(PlatformBufferIPCPackaging, test_ipc_data_packed_correctly_for_nested)
806-{
807- using namespace ::testing;
808- EXPECT_CALL(*native_buffer, copy_fence())
809- .WillOnce(Return(-1));
810-
811- mga::Platform platform(stub_display_builder, stub_display_report);
812-
813- mtd::MockBufferIpcMessage mock_ipc_msg;
814- int offset = 0;
815- for (auto i = 0u; i < num_fds; i++)
816- {
817- EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(native_buffer_handle->data[offset++])))
818- .Times(1);
819- }
820- EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::unfenced)));
821- for (auto i = 0u; i < num_ints; i++)
822- {
823- EXPECT_CALL(mock_ipc_msg, pack_data(native_buffer_handle->data[offset++]))
824- .Times(1);
825- }
826-
827- EXPECT_CALL(*mock_buffer, stride())
828- .WillOnce(Return(stride));
829- EXPECT_CALL(mock_ipc_msg, pack_stride(stride))
830- .Times(1);
831-
832- EXPECT_CALL(*mock_buffer, size())
833- .WillOnce(Return(mir::geometry::Size{123, 456}));
834- EXPECT_CALL(mock_ipc_msg, pack_size(_))
835- .Times(1);
836-
837- platform.fill_buffer_package(&mock_ipc_msg, mock_buffer.get(), mg::BufferIpcMsgType::full_msg);
838-}
839-
840-TEST_F(PlatformBufferIPCPackaging, test_ipc_data_packed_correctly_for_partial_ipc)
841-{
842- using namespace ::testing;
843-
844- int fake_fence{33};
845- mga::Platform platform(stub_display_builder, stub_display_report);
846- auto ipc_ops = platform.make_ipc_operations();
847-
848- mtd::MockBufferIpcMessage mock_ipc_msg;
849-
850- Sequence seq;
851- EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::fenced)))
852- .InSequence(seq);
853- EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(fake_fence)))
854- .InSequence(seq);
855- EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::unfenced)))
856- .InSequence(seq);
857-
858- EXPECT_CALL(*native_buffer, copy_fence())
859- .Times(2)
860- .WillOnce(Return(fake_fence))
861- .WillOnce(Return(-1));
862-
863- ipc_ops->pack_buffer(mock_ipc_msg, *mock_buffer, mg::BufferIpcMsgType::update_msg);
864- ipc_ops->pack_buffer(mock_ipc_msg, *mock_buffer, mg::BufferIpcMsgType::update_msg);
865+
866+TEST(PlatformBufferIPCPackaging, test_ipc_data_packed_correctly_for_nested)
867+{
868+ using namespace ::testing;
869+ unsigned int num_ints{43};
870+ unsigned int num_fds{55};
871+ int offset = 0;
872+ geom::Stride stride{300*4};
873+ geom::Size size{123, 456};
874+ mtd::MockBuffer mock_buffer;
875+ mtd::MockBufferIpcMessage mock_ipc_msg;
876+
877+ auto native_buffer = std::make_shared<mtd::MockAndroidNativeBuffer>();
878+ auto native = mtd::generate_native_handle(num_ints, num_fds);
879+ ON_CALL(*native_buffer, handle())
880+ .WillByDefault(Return(native.get()));
881+ ON_CALL(mock_buffer, native_buffer_handle())
882+ .WillByDefault(Return(native_buffer));
883+ ON_CALL(mock_buffer, stride())
884+ .WillByDefault(Return(stride));
885+ ON_CALL(mock_buffer, size())
886+ .WillByDefault(Return(size));
887+
888+ mga::Platform platform(std::make_shared<mtd::StubDisplayBuilder>(), mr::null_display_report());
889+
890+ EXPECT_CALL(*native_buffer, copy_fence())
891+ .WillOnce(Return(-1));
892+ EXPECT_CALL(mock_ipc_msg, pack_data(static_cast<int>(mga::BufferFlag::unfenced)));
893+ for (auto i = 0u; i < num_fds; i++)
894+ EXPECT_CALL(mock_ipc_msg, pack_fd(mtd::RawFdMatcher(native->data[offset++])));
895+ for (auto i = 0u; i < num_ints; i++)
896+ EXPECT_CALL(mock_ipc_msg, pack_data(native->data[offset++]));
897+ EXPECT_CALL(mock_ipc_msg, pack_stride(stride));
898+ EXPECT_CALL(mock_ipc_msg, pack_size(size));
899+
900+ platform.fill_buffer_package(&mock_ipc_msg, &mock_buffer, mg::BufferIpcMsgType::full_msg);
901 }
902
903 TEST(AndroidGraphicsPlatform, egl_native_display_is_egl_default_display)

Subscribers

People subscribed via source and target branches