2
* Copyright Ā© 2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* 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: Kevin DuBois <kevin.dubois@canonical.com>
19
#include "src/platform/graphics/android/display_buffer.h"
20
#include "src/platform/graphics/android/android_display.h"
21
#include "src/platform/graphics/android/gl_context.h"
22
#include "src/platform/graphics/android/android_format_conversion-inl.h"
23
#include "mir_test_doubles/mock_display_device.h"
24
#include "mir_test_doubles/mock_display_report.h"
25
#include "mir_test_doubles/stub_renderable.h"
26
#include "mir_test_doubles/mock_egl.h"
27
#include "mir_test_doubles/mock_gl.h"
28
#include "mir/graphics/android/mir_native_window.h"
29
#include "mir_test_doubles/stub_driver_interpreter.h"
30
#include "mir_test_doubles/stub_display_buffer.h"
31
#include "mir_test_doubles/stub_buffer.h"
32
#include "mir_test_doubles/stub_gl_config.h"
33
#include "mir_test_doubles/mock_framebuffer_bundle.h"
34
#include "mir_test_doubles/stub_gl_program_factory.h"
37
namespace geom=mir::geometry;
38
namespace mg=mir::graphics;
39
namespace mga=mir::graphics::android;
40
namespace mtd=mir::test::doubles;
44
class AndroidDisplayBuffer : public ::testing::Test
49
stub_buffer = std::make_shared<testing::NiceMock<mtd::StubBuffer>>();
50
mock_display_device = std::make_shared<testing::NiceMock<mtd::MockDisplayDevice>>();
51
native_window = std::make_shared<mg::android::MirNativeWindow>(std::make_shared<mtd::StubDriverInterpreter>());
54
dummy_display = mock_egl.fake_egl_display;
55
dummy_config = mock_egl.fake_configs[0];
56
dummy_context = mock_egl.fake_egl_context;
57
testing::NiceMock<mtd::MockDisplayReport> report;
58
mtd::StubGLConfig stub_gl_config;
60
gl_context = std::make_shared<mga::PbufferGLContext>(
61
mga::to_mir_format(mock_egl.fake_visual_id), stub_gl_config, report);
63
mock_fb_bundle = std::make_shared<testing::NiceMock<mtd::MockFBBundle>>();
65
ON_CALL(*mock_fb_bundle, fb_format())
66
.WillByDefault(testing::Return(mir_pixel_format_abgr_8888));
67
ON_CALL(*mock_fb_bundle, fb_size())
68
.WillByDefault(testing::Return(display_size));
69
ON_CALL(*mock_fb_bundle, fb_refresh_rate())
70
.WillByDefault(testing::Return(refresh_rate));
73
testing::NiceMock<mtd::MockEGL> mock_egl;
74
testing::NiceMock<mtd::MockGL> mock_gl;
75
mtd::StubGLProgramFactory stub_program_factory;
78
EGLConfig dummy_config;
79
EGLDisplay dummy_display;
80
EGLContext dummy_context;
81
std::shared_ptr<mga::GLContext> gl_context;
83
std::shared_ptr<mtd::StubBuffer> stub_buffer;
84
std::shared_ptr<ANativeWindow> native_window;
85
std::shared_ptr<mtd::MockDisplayDevice> mock_display_device;
86
std::shared_ptr<mtd::MockFBBundle> mock_fb_bundle;
87
geom::Size const display_size{433,232};
88
double const refresh_rate{60.0};
92
TEST_F(AndroidDisplayBuffer, can_post_update_with_gl_only)
94
using namespace testing;
97
EXPECT_CALL(*mock_display_device, post_gl(_))
100
mg::RenderableList renderlist{};
101
mga::DisplayBuffer db(
102
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
106
TEST_F(AndroidDisplayBuffer, posts_overlay_list_returns_display_device_decision)
108
using namespace testing;
109
mg::RenderableList renderlist{
110
std::make_shared<mtd::StubRenderable>(),
111
std::make_shared<mtd::StubRenderable>()};
113
EXPECT_CALL(*mock_display_device, post_overlays(_, Ref(renderlist), _))
115
.WillOnce(Return(true))
116
.WillOnce(Return(false));
118
mga::DisplayBuffer db(
119
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
120
EXPECT_TRUE(db.post_renderables_if_optimizable(renderlist));
121
EXPECT_FALSE(db.post_renderables_if_optimizable(renderlist));
124
TEST_F(AndroidDisplayBuffer, defaults_to_normal_orientation)
126
mga::DisplayBuffer db(
127
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
129
EXPECT_EQ(mir_orientation_normal, db.orientation());
132
TEST_F(AndroidDisplayBuffer, orientation_is_passed_through)
134
mga::DisplayBuffer db(
135
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
137
for (auto const& ori : {mir_orientation_normal,
138
mir_orientation_left,
139
mir_orientation_right,
140
mir_orientation_inverted})
142
auto config = db.configuration();
143
config.orientation = ori;
144
db.configure(config);
145
EXPECT_EQ(ori, db.orientation());
149
TEST_F(AndroidDisplayBuffer, rotation_transposes_dimensions)
151
using namespace testing;
153
int const width = 123;
154
int const height = 456;
155
geom::Size const normal{width, height};
156
geom::Size const transposed{height, width};
158
EXPECT_CALL(*mock_fb_bundle, fb_size())
159
.WillRepeatedly(Return(normal));
161
mga::DisplayBuffer db(
162
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
164
EXPECT_EQ(normal, db.view_area().size);
166
auto config = db.configuration();
168
config.orientation = mir_orientation_right;
169
db.configure(config);
170
EXPECT_EQ(transposed, db.view_area().size);
172
config.orientation = mir_orientation_inverted;
173
db.configure(config);
174
EXPECT_EQ(normal, db.view_area().size);
176
config.orientation = mir_orientation_left;
177
db.configure(config);
178
EXPECT_EQ(transposed, db.view_area().size);
181
TEST_F(AndroidDisplayBuffer, reports_correct_size)
183
using namespace testing;
185
mga::DisplayBuffer db(
186
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
188
auto view_area = db.view_area();
190
geom::Point origin_pt{geom::X{0}, geom::Y{0}};
191
EXPECT_EQ(display_size, view_area.size);
192
EXPECT_EQ(origin_pt, view_area.top_left);
195
TEST_F(AndroidDisplayBuffer, creates_egl_context_from_shared_context)
197
using namespace testing;
199
EGLint const expected_attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
201
EXPECT_CALL(mock_egl, eglCreateContext(
202
dummy_display, _, dummy_context, mtd::AttrMatches(expected_attr)))
204
.WillOnce(Return(mock_egl.fake_egl_context));
205
EXPECT_CALL(mock_egl, eglCreateWindowSurface(
206
dummy_display, _, native_window.get(), NULL))
208
.WillOnce(Return(mock_egl.fake_egl_surface));
209
EXPECT_CALL(mock_egl, eglDestroySurface(dummy_display, mock_egl.fake_egl_surface))
211
EXPECT_CALL(mock_egl, eglDestroyContext(dummy_display, mock_egl.fake_egl_context))
214
mga::DisplayBuffer db(
215
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
216
testing::Mock::VerifyAndClearExpectations(&mock_egl);
219
TEST_F(AndroidDisplayBuffer, fails_on_egl_resource_creation)
221
using namespace testing;
222
EXPECT_CALL(mock_egl, eglCreateContext(_,_,_,_))
224
.WillOnce(Return(EGL_NO_CONTEXT))
225
.WillOnce(Return(mock_egl.fake_egl_context));
226
EXPECT_CALL(mock_egl, eglCreateWindowSurface(_,_,_,_))
228
.WillOnce(Return(EGL_NO_SURFACE));
232
mga::DisplayBuffer db(
233
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
234
}, std::runtime_error);
238
mga::DisplayBuffer db(
239
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
240
}, std::runtime_error);
243
TEST_F(AndroidDisplayBuffer, can_make_current)
245
using namespace testing;
246
EGLContext fake_ctxt = reinterpret_cast<EGLContext>(0x4422);
247
EGLSurface fake_surf = reinterpret_cast<EGLSurface>(0x33984);
248
ON_CALL(mock_egl, eglCreateContext(_,_,_,_))
249
.WillByDefault(Return(fake_ctxt));
250
ON_CALL(mock_egl, eglCreateWindowSurface(_,_,_,_))
251
.WillByDefault(Return(fake_surf));
253
mga::DisplayBuffer db(
254
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
256
EXPECT_CALL(mock_egl, eglMakeCurrent(dummy_display, fake_surf, fake_surf, fake_ctxt))
258
.WillOnce(Return(EGL_TRUE))
259
.WillOnce(Return(EGL_FALSE));
265
}, std::runtime_error);
268
TEST_F(AndroidDisplayBuffer, release_current)
270
using namespace testing;
271
mga::DisplayBuffer db(
272
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
274
EXPECT_CALL(mock_egl, eglMakeCurrent(dummy_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
276
db.release_current();
279
TEST_F(AndroidDisplayBuffer, sets_display_power_mode_to_on_at_start)
281
using namespace testing;
282
mga::DisplayBuffer db(
283
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
284
auto config = db.configuration();
285
EXPECT_EQ(mir_power_mode_on, config.power_mode);
288
TEST_F(AndroidDisplayBuffer, changes_display_power_mode)
290
using namespace testing;
291
mga::DisplayBuffer db(
292
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
295
EXPECT_CALL(*mock_display_device, mode(mir_power_mode_off))
297
EXPECT_CALL(*mock_display_device, mode(mir_power_mode_on))
300
auto config = db.configuration();
301
config.power_mode = mir_power_mode_off;
302
db.configure(config);
304
config = db.configuration();
305
config.power_mode = mir_power_mode_on;
306
db.configure(config);
309
TEST_F(AndroidDisplayBuffer, disregards_double_display_power_mode_request)
311
using namespace testing;
312
mga::DisplayBuffer db(
313
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
315
EXPECT_CALL(*mock_display_device, mode(mir_power_mode_off))
318
auto config = db.configuration();
319
config.power_mode = mir_power_mode_off;
320
db.configure(config);
321
config.power_mode = mir_power_mode_suspend;
322
db.configure(config);
323
config.power_mode = mir_power_mode_standby;
324
db.configure(config);
327
//configuration tests
328
TEST_F(AndroidDisplayBuffer, display_orientation_supported)
330
using namespace testing;
332
EXPECT_CALL(*mock_display_device, apply_orientation(mir_orientation_left))
334
.WillOnce(Return(true));
336
mga::DisplayBuffer db(
337
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
339
auto config = db.configuration();
340
config.orientation = mir_orientation_left;
341
db.configure(config);
343
config = db.configuration();
344
EXPECT_EQ(mir_orientation_normal, config.orientation);
347
TEST_F(AndroidDisplayBuffer, display_orientation_not_supported)
349
using namespace testing;
350
EXPECT_CALL(*mock_display_device, apply_orientation(mir_orientation_left))
352
.WillOnce(Return(false));
354
mga::DisplayBuffer db(
355
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
357
auto config = db.configuration();
358
config.orientation = mir_orientation_left;
359
db.configure(config);
361
config = db.configuration();
362
EXPECT_EQ(mir_orientation_left, config.orientation);
365
TEST_F(AndroidDisplayBuffer, incorrect_display_configure_throws)
367
mga::DisplayBuffer db(
368
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
369
auto config = db.configuration();
371
config.current_format = mir_pixel_format_invalid;
373
db.configure(config);
374
}, std::runtime_error);
377
TEST_F(AndroidDisplayBuffer, android_display_configuration_info)
379
mga::DisplayBuffer db(
380
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
381
auto disp_conf = db.configuration();
383
ASSERT_EQ(1u, disp_conf.modes.size());
384
auto& disp_mode = disp_conf.modes[0];
385
EXPECT_EQ(display_size, disp_mode.size);
387
EXPECT_EQ(mg::DisplayConfigurationOutputId{1}, disp_conf.id);
388
EXPECT_EQ(mg::DisplayConfigurationCardId{0}, disp_conf.card_id);
389
EXPECT_TRUE(disp_conf.connected);
390
EXPECT_TRUE(disp_conf.used);
391
auto origin = geom::Point{0,0};
392
EXPECT_EQ(origin, disp_conf.top_left);
393
EXPECT_EQ(0, disp_conf.current_mode_index);
395
EXPECT_EQ(refresh_rate, disp_mode.vrefresh_hz);
396
//TODO fill physical_size_mm fields accordingly;
399
TEST_F(AndroidDisplayBuffer, does_not_use_alpha)
401
mga::DisplayBuffer db(
402
mock_fb_bundle, mock_display_device, native_window, *gl_context, stub_program_factory, mga::OverlayOptimization::enabled);
404
EXPECT_FALSE(db.uses_alpha());
407
TEST_F(AndroidDisplayBuffer, reject_list_if_option_disabled)
409
mg::RenderableList renderlist{std::make_shared<mtd::StubRenderable>()};
410
mga::DisplayBuffer db(
415
stub_program_factory,
416
mga::OverlayOptimization::disabled);
418
EXPECT_FALSE(db.post_renderables_if_optimizable(renderlist));