2
* Copyright Ā© 2012 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 "mir/graphics/display_buffer.h"
20
#include "mir/graphics/display_configuration.h"
21
#include "mir/logging/logger.h"
22
#include "src/platform/graphics/android/android_display.h"
23
#include "src/server/report/null_report_factory.h"
24
#include "mir_test_doubles/mock_display_report.h"
25
#include "mir_test_doubles/mock_display_device.h"
26
#include "mir_test_doubles/mock_egl.h"
27
#include "mir_test_doubles/stub_display_buffer.h"
28
#include "mir_test_doubles/stub_display_builder.h"
29
#include "mir_test_doubles/stub_gl_config.h"
30
#include "mir_test_doubles/mock_gl_config.h"
31
#include "mir_test_doubles/stub_gl_program_factory.h"
32
#include "mir/graphics/android/mir_native_window.h"
33
#include "mir_test_doubles/stub_driver_interpreter.h"
35
#include <gtest/gtest.h>
38
#include <unordered_set>
41
namespace mg=mir::graphics;
42
namespace mga=mir::graphics::android;
43
namespace mtd=mir::test::doubles;
44
namespace geom=mir::geometry;
46
class AndroidDisplay : public ::testing::Test
50
: dummy_display{mock_egl.fake_egl_display},
51
dummy_context{mock_egl.fake_egl_context},
52
dummy_config{mock_egl.fake_configs[0]},
53
null_display_report{mir::report::null_display_report()},
54
stub_db_factory{std::make_shared<mtd::StubDisplayBuilder>()},
55
stub_gl_config{std::make_shared<mtd::StubGLConfig>()},
56
stub_gl_program_factory{std::make_shared<mtd::StubGLProgramFactory>()}
61
testing::NiceMock<mtd::MockEGL> mock_egl;
62
EGLDisplay const dummy_display;
63
EGLContext const dummy_context;
64
EGLConfig const dummy_config;
66
std::shared_ptr<mg::DisplayReport> const null_display_report;
67
std::shared_ptr<mtd::StubDisplayBuilder> const stub_db_factory;
68
std::shared_ptr<mtd::StubGLConfig> const stub_gl_config;
69
std::shared_ptr<mtd::StubGLProgramFactory> const stub_gl_program_factory;
72
TEST_F(AndroidDisplay, creation_creates_egl_resources_properly)
74
using namespace testing;
75
EGLSurface fake_surface = (EGLSurface) 0x715;
76
EGLint const expected_pbuffer_attr[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
77
EGLint const expected_context_attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
80
EXPECT_CALL(mock_egl, eglGetDisplay(EGL_DEFAULT_DISPLAY))
82
.WillOnce(Return(dummy_display));
83
EXPECT_CALL(mock_egl, eglInitialize(dummy_display, _, _))
85
.WillOnce(DoAll(SetArgPointee<1>(1), SetArgPointee<2>(4), Return(EGL_TRUE)));
86
EXPECT_CALL(mock_egl, eglCreateContext(
87
dummy_display, _, EGL_NO_CONTEXT, mtd::AttrMatches(expected_context_attr)))
89
.WillOnce(Return(dummy_context));
90
EXPECT_CALL(mock_egl, eglCreatePbufferSurface(
91
dummy_display, _, mtd::AttrMatches(expected_pbuffer_attr)))
93
.WillOnce(Return(fake_surface));
94
EXPECT_CALL(mock_egl, eglMakeCurrent(dummy_display, fake_surface, fake_surface, dummy_context))
98
EXPECT_CALL(mock_egl, eglGetCurrentContext())
100
.WillOnce(Return(dummy_context));
101
EXPECT_CALL(mock_egl, eglMakeCurrent(dummy_display,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT))
103
EXPECT_CALL(mock_egl, eglDestroySurface(dummy_display, fake_surface))
105
EXPECT_CALL(mock_egl, eglDestroyContext(dummy_display, dummy_context))
107
EXPECT_CALL(mock_egl, eglTerminate(dummy_display))
110
mga::AndroidDisplay display(
112
stub_gl_program_factory,
114
null_display_report);
117
TEST_F(AndroidDisplay, selects_usable_configuration)
119
using namespace testing;
120
int const incorrect_visual_id = 2;
121
int const correct_visual_id = 1;
122
EGLint const num_cfgs = 45;
123
EGLint const expected_cfg_attr [] = {
124
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
125
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
129
EGLConfig selected_config;
131
for(auto i = 0; i < num_cfgs; i++)
132
cfgs[i] = reinterpret_cast<EGLConfig>(i);
133
int config_to_select_index = 37;
134
EGLConfig correct_config = cfgs[config_to_select_index];
136
ON_CALL(mock_egl, eglGetConfigAttrib(_, _, EGL_NATIVE_VISUAL_ID, _))
137
.WillByDefault(DoAll(SetArgPointee<3>(incorrect_visual_id), Return(EGL_TRUE)));
138
ON_CALL(mock_egl, eglGetConfigAttrib(dummy_display, correct_config, EGL_NATIVE_VISUAL_ID,_))
139
.WillByDefault(DoAll(SetArgPointee<3>(correct_visual_id), Return(EGL_TRUE)));
140
ON_CALL(mock_egl, eglCreateContext(_,_,_,_))
141
.WillByDefault(DoAll(SaveArg<1>(&selected_config),Return(dummy_context)));
143
auto config_filler = [&]
144
(EGLDisplay, EGLint const*, EGLConfig* out_cfgs, EGLint, EGLint* out_num_cfgs) -> EGLBoolean
146
memcpy(out_cfgs, cfgs, sizeof(EGLConfig) * num_cfgs);
147
*out_num_cfgs = num_cfgs;
151
EXPECT_CALL(mock_egl, eglGetConfigs(dummy_display, NULL, 0, _))
153
.WillOnce(DoAll(SetArgPointee<3>(num_cfgs), Return(EGL_TRUE)));
154
EXPECT_CALL(mock_egl, eglChooseConfig(dummy_display, mtd::AttrMatches(expected_cfg_attr),_,num_cfgs,_))
156
.WillOnce(Invoke(config_filler));
158
mga::AndroidDisplay display(
160
stub_gl_program_factory,
162
null_display_report);
163
EXPECT_EQ(correct_config, selected_config);
166
TEST_F(AndroidDisplay, respects_gl_config)
168
using namespace testing;
170
auto const mock_gl_config = std::make_shared<mtd::MockGLConfig>();
171
EGLint const depth_bits{24};
172
EGLint const stencil_bits{8};
174
EXPECT_CALL(*mock_gl_config, depth_buffer_bits())
175
.WillOnce(Return(depth_bits));
176
EXPECT_CALL(*mock_gl_config, stencil_buffer_bits())
177
.WillOnce(Return(stencil_bits));
179
EXPECT_CALL(mock_egl,
182
AllOf(mtd::EGLConfigContainsAttrib(EGL_DEPTH_SIZE, depth_bits),
183
mtd::EGLConfigContainsAttrib(EGL_STENCIL_SIZE, stencil_bits)),
186
mga::AndroidDisplay display(
188
stub_gl_program_factory,
190
null_display_report);
193
TEST_F(AndroidDisplay, logs_creation_events)
195
using namespace testing;
197
auto const mock_display_report = std::make_shared<mtd::MockDisplayReport>();
199
EXPECT_CALL(*mock_display_report, report_successful_setup_of_native_resources())
201
EXPECT_CALL(*mock_display_report, report_egl_configuration(_,_))
203
EXPECT_CALL(*mock_display_report, report_successful_egl_make_current_on_construction())
205
EXPECT_CALL(*mock_display_report, report_successful_display_construction())
208
mga::AndroidDisplay display(
210
stub_gl_program_factory,
212
mock_display_report);
215
TEST_F(AndroidDisplay, throws_on_eglMakeCurrent_failure)
217
using namespace testing;
219
auto const mock_display_report = std::make_shared<NiceMock<mtd::MockDisplayReport>>();
221
EXPECT_CALL(*mock_display_report, report_successful_setup_of_native_resources())
223
EXPECT_CALL(mock_egl, eglMakeCurrent(dummy_display, _, _, _))
225
.WillOnce(Return(EGL_FALSE));
226
EXPECT_CALL(*mock_display_report, report_successful_egl_make_current_on_construction())
228
EXPECT_CALL(*mock_display_report, report_successful_display_construction())
232
mga::AndroidDisplay display(
234
stub_gl_program_factory,
236
mock_display_report);
237
}, std::runtime_error);
240
TEST_F(AndroidDisplay, logs_error_because_of_surface_creation_failure)
242
using namespace testing;
244
auto const mock_display_report = std::make_shared<mtd::MockDisplayReport>();
246
EXPECT_CALL(*mock_display_report, report_successful_setup_of_native_resources())
248
EXPECT_CALL(*mock_display_report, report_successful_egl_make_current_on_construction())
250
EXPECT_CALL(*mock_display_report, report_successful_display_construction())
253
EXPECT_CALL(mock_egl, eglCreatePbufferSurface(_,_,_))
255
.WillOnce(Return(EGL_NO_SURFACE));
258
mga::AndroidDisplay display(
260
stub_gl_program_factory,
262
mock_display_report);
263
}, std::runtime_error);
266
TEST_F(AndroidDisplay, configures_display_buffer)
268
using namespace testing;
269
mga::AndroidDisplay display(
271
stub_gl_program_factory,
273
null_display_report);
275
auto configuration = display.configuration();
276
configuration->for_each_output([&](mg::UserDisplayConfigurationOutput& output)
278
output.power_mode = mir_power_mode_on;
280
display.configure(*configuration);
282
configuration->for_each_output([&](mg::UserDisplayConfigurationOutput& output)
284
output.power_mode = mir_power_mode_standby;
286
display.configure(*configuration);
288
configuration->for_each_output([&](mg::UserDisplayConfigurationOutput& output)
290
output.power_mode = mir_power_mode_off;
292
display.configure(*configuration);
294
configuration->for_each_output([&](mg::UserDisplayConfigurationOutput& output)
296
output.power_mode = mir_power_mode_suspend;
298
display.configure(*configuration);
301
//we only have single display and single mode on android for the time being
302
TEST_F(AndroidDisplay, supports_one_output_configuration)
304
mga::AndroidDisplay display(
306
stub_gl_program_factory,
308
null_display_report);
309
auto config = display.configuration();
311
size_t num_configs = 0;
312
config->for_each_output([&](mg::DisplayConfigurationOutput const&)
317
EXPECT_EQ(1u, num_configs);