20
20
#include "mir/compositor/display_buffer_compositor.h"
21
21
#include "mir/compositor/scene.h"
22
22
#include "mir/compositor/display_buffer_compositor_factory.h"
23
#include "mir/compositor/compositor_report.h"
23
24
#include "mir_test_doubles/null_display.h"
24
25
#include "mir_test_doubles/null_display_buffer.h"
25
26
#include "mir_test_doubles/mock_display_buffer.h"
27
#include "mir_test_doubles/mock_compositor_report.h"
27
29
#include <unordered_map>
28
30
#include <unordered_set>
113
115
std::mutex callback_mutex;
118
class MockScene : public mc::Scene
121
MOCK_METHOD2(for_each_if, void(mc::FilterForScene&, mc::OperatorForScene&));
122
MOCK_METHOD2(reverse_for_each_if, void(mc::FilterForScene&, mc::OperatorForScene&));
123
MOCK_METHOD1(set_change_callback, void(std::function<void()> const&));
124
MOCK_METHOD0(lock, void());
125
MOCK_METHOD0(unlock, void());
116
128
class RecordingDisplayBufferCompositor : public mc::DisplayBufferCompositor
307
321
auto display = std::make_shared<StubDisplay>(nbuffers);
308
322
auto scene = std::make_shared<StubScene>();
309
323
auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>();
310
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory};
324
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
312
326
compositor.start();
320
334
EXPECT_TRUE(db_compositor_factory->buffers_rendered_in_different_threads());
337
TEST(MultiThreadedCompositor, reports_in_the_right_places)
339
using namespace testing;
341
auto display = std::make_shared<StubDisplayWithMockBuffers>(1);
342
auto scene = std::make_shared<StubScene>();
343
auto db_compositor_factory =
344
std::make_shared<RecordingDisplayBufferCompositorFactory>();
345
auto mock_report = std::make_shared<mtd::MockCompositorReport>();
346
mc::MultiThreadedCompositor compositor{display, scene,
347
db_compositor_factory,
350
EXPECT_CALL(*mock_report, started())
353
display->for_each_mock_buffer([](mtd::MockDisplayBuffer& mock_buf)
355
EXPECT_CALL(mock_buf, make_current()).Times(1);
356
EXPECT_CALL(mock_buf, view_area())
357
.WillOnce(Return(geom::Rectangle()));
360
EXPECT_CALL(*mock_report, added_display(_,_,_,_,_))
362
EXPECT_CALL(*mock_report, scheduled())
365
display->for_each_mock_buffer([](mtd::MockDisplayBuffer& mock_buf)
367
EXPECT_CALL(mock_buf, release_current()).Times(1);
370
EXPECT_CALL(*mock_report, stopped())
374
scene->emit_change_event();
375
while (!db_compositor_factory->check_record_count_for_each_buffer(1, mc::max_client_buffers))
376
std::this_thread::yield();
324
381
* It's difficult to test that a render won't happen, without some further
325
382
* introspective capabilities that would complicate the code. This test will
338
395
auto display = std::make_shared<StubDisplay>(nbuffers);
339
396
auto scene = std::make_shared<StubScene>();
340
397
auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>();
341
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory};
398
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
343
400
// Verify we're actually starting at zero frames
344
401
EXPECT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, 0, 0));
398
455
auto display = std::make_shared<StubDisplay>(nbuffers);
399
456
auto scene = std::make_shared<StubScene>();
400
457
auto db_compositor_factory = std::make_shared<SurfaceUpdatingDisplayBufferCompositorFactory>(scene);
401
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory};
458
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
403
460
compositor.start();
417
474
auto display = std::make_shared<StubDisplayWithMockBuffers>(nbuffers);
418
475
auto scene = std::make_shared<StubScene>();
419
476
auto db_compositor_factory = std::make_shared<NullDisplayBufferCompositorFactory>();
420
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory};
477
mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
422
479
display->for_each_mock_buffer([](mtd::MockDisplayBuffer& mock_buf)
481
EXPECT_CALL(mock_buf, view_area())
482
.WillOnce(Return(geom::Rectangle()));
424
483
EXPECT_CALL(mock_buf, make_current()).Times(1);
425
484
EXPECT_CALL(mock_buf, release_current()).Times(1);
428
487
compositor.start();
429
488
compositor.stop();
491
TEST(MultiThreadedCompositor, double_start_or_stop_ignored)
493
unsigned int const nbuffers{3};
494
auto display = std::make_shared<StubDisplayWithMockBuffers>(nbuffers);
495
auto mock_scene = std::make_shared<MockScene>();
496
auto db_compositor_factory = std::make_shared<NullDisplayBufferCompositorFactory>();
497
auto mock_report = std::make_shared<testing::NiceMock<mtd::MockCompositorReport>>();
498
EXPECT_CALL(*mock_report, started())
500
EXPECT_CALL(*mock_report, stopped())
502
EXPECT_CALL(*mock_scene, set_change_callback(testing::_))
505
mc::MultiThreadedCompositor compositor{display, mock_scene, db_compositor_factory, mock_report};