2
* Copyright © 2014 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
19
#include "mir_toolkit/mir_client_library.h"
20
#include "mir_toolkit/mir_client_library_debug.h"
22
#include "mir/compositor/compositor.h"
23
#include "mir/compositor/renderer_factory.h"
24
#include "mir/graphics/renderable.h"
25
#include "mir/graphics/buffer.h"
26
#include "mir/graphics/buffer_id.h"
28
#include "mir_test_framework/using_stub_client_platform.h"
29
#include "mir_test_framework/stubbed_server_configuration.h"
30
#include "mir_test_framework/basic_client_server_fixture.h"
31
#include "mir_test_doubles/stub_renderer.h"
33
#include <gtest/gtest.h>
34
#include <gmock/gmock.h>
37
#include <condition_variable>
39
namespace mtf = mir_test_framework;
40
namespace mtd = mir::test::doubles;
41
namespace mc = mir::compositor;
42
namespace mg = mir::graphics;
43
namespace geom = mir::geometry;
48
struct StubRenderer : mtd::StubRenderer
50
void render(mg::RenderableList const& renderables) const override
52
std::lock_guard<std::mutex> lock{mutex};
53
for (auto const& r : renderables)
54
rendered_buffers_.push_back(r->buffer()->id());
56
if (renderables.size() > 0)
57
new_rendered_buffer_cv.notify_all();
60
std::vector<mg::BufferID> rendered_buffers()
62
std::lock_guard<std::mutex> lock{mutex};
63
return rendered_buffers_;
66
std::vector<mg::BufferID> wait_for_new_rendered_buffers()
68
std::unique_lock<std::mutex> lock{mutex};
70
new_rendered_buffer_cv.wait_for(
71
lock, std::chrono::seconds{2},
72
[this] { return rendered_buffers_.size() != 0; });
74
auto const rendered = std::move(rendered_buffers_);
78
mutable std::mutex mutex;
79
mutable std::condition_variable new_rendered_buffer_cv;
80
mutable std::vector<mg::BufferID> rendered_buffers_;
83
class StubRendererFactory : public mc::RendererFactory
86
std::unique_ptr<mc::Renderer> create_renderer_for(
87
geom::Rectangle const&, mc::DestinationAlpha) override
89
std::lock_guard<std::mutex> lock{mutex};
90
renderer_ = new StubRenderer();
91
renderer_created_cv.notify_all();
92
return std::unique_ptr<mc::Renderer>{renderer_};
95
StubRenderer* renderer()
97
std::unique_lock<std::mutex> lock{mutex};
99
renderer_created_cv.wait_for(
100
lock, std::chrono::seconds{2},
101
[this] { return renderer_ != nullptr; });
106
void clear_renderer()
108
std::lock_guard<std::mutex> lock{mutex};
113
std::condition_variable renderer_created_cv;
114
StubRenderer* renderer_ = nullptr;
117
struct StubServerConfig : mtf::StubbedServerConfiguration
119
std::shared_ptr<StubRendererFactory> the_stub_renderer_factory()
121
return stub_renderer_factory(
122
[] { return std::make_shared<StubRendererFactory>(); });
125
std::shared_ptr<mc::RendererFactory> the_renderer_factory() override
127
return the_stub_renderer_factory();
130
mir::CachedPtr<StubRendererFactory> stub_renderer_factory;
133
using BasicFixture = mtf::BasicClientServerFixture<StubServerConfig>;
135
struct StaleFrames : BasicFixture
139
BasicFixture::SetUp();
141
client_create_surface();
146
mir_surface_release_sync(surface);
148
BasicFixture::TearDown();
151
void client_create_surface()
153
MirSurfaceParameters const request_params =
157
mir_pixel_format_abgr_8888,
158
mir_buffer_usage_hardware,
159
mir_display_output_id_invalid
162
surface = mir_connection_create_surface_sync(connection, &request_params);
163
ASSERT_TRUE(mir_surface_is_valid(surface));
166
std::vector<mg::BufferID> wait_for_new_rendered_buffers()
168
return server_configuration.the_stub_renderer_factory()->renderer()->wait_for_new_rendered_buffers();
171
void stop_compositor()
173
server_configuration.the_compositor()->stop();
174
server_configuration.the_stub_renderer_factory()->clear_renderer();
177
void start_compositor()
179
server_configuration.the_compositor()->start();
183
mtf::UsingStubClientPlatform using_stub_client_platform;
188
TEST_F(StaleFrames, are_dropped_when_restarting_compositor)
190
using namespace testing;
194
auto const stale_buffer_id1 = mg::BufferID{mir_debug_surface_current_buffer_id(surface)};
195
mir_surface_swap_buffers_sync(surface);
197
auto const stale_buffer_id2 = mg::BufferID{mir_debug_surface_current_buffer_id(surface)};
198
mir_surface_swap_buffers_sync(surface);
200
mir_surface_swap_buffers_sync(surface);
204
auto const new_buffers = wait_for_new_rendered_buffers();
205
EXPECT_THAT(new_buffers, Not(AnyOf(Contains(stale_buffer_id1), Contains(stale_buffer_id2))));