~ubuntu-branches/ubuntu/wily/mir/wily-proposed

« back to all changes in this revision

Viewing changes to tests/unit-tests/graphics/gbm/test_gbm_display_configuration.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2014-01-08 02:04:38 UTC
  • mto: This revision was merged to the branch mainline in revision 58.
  • Revision ID: package-import@ubuntu.com-20140108020438-e1npu0pm7qdv5wc4
Tags: upstream-0.1.3+14.04.20140108
ImportĀ upstreamĀ versionĀ 0.1.3+14.04.20140108

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright Ā© 2013 Canonical Ltd.
3
 
 *
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.
7
 
 *
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.
12
 
 *
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/>.
15
 
 *
16
 
 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
17
 
 */
18
 
 
19
 
#include <boost/throw_exception.hpp>
20
 
#include "mir/graphics/display_configuration.h"
21
 
#include "mir/graphics/display.h"
22
 
#include "src/server/graphics/default_display_configuration_policy.h"
23
 
#include "src/server/graphics/gbm/gbm_platform.h"
24
 
#include "src/server/graphics/gbm/gbm_display.h"
25
 
#include "src/server/graphics/gbm/kms_display_configuration.h"
26
 
 
27
 
#include "mir_test_doubles/mock_egl.h"
28
 
#include "mir_test_doubles/mock_gl.h"
29
 
#include "mir/graphics/null_display_report.h"
30
 
#include "mir_test_doubles/null_virtual_terminal.h"
31
 
 
32
 
#include "mir_test_framework/udev_environment.h"
33
 
 
34
 
#include "mir_test_doubles/mock_drm.h"
35
 
#include "mir_test_doubles/mock_gbm.h"
36
 
 
37
 
#include <gmock/gmock.h>
38
 
#include <gtest/gtest.h>
39
 
 
40
 
#include <stdexcept>
41
 
 
42
 
namespace mg = mir::graphics;
43
 
namespace mgg = mir::graphics::gbm;
44
 
namespace geom = mir::geometry;
45
 
namespace mtd = mir::test::doubles;
46
 
namespace mtf = mir::mir_test_framework;
47
 
 
48
 
namespace
49
 
{
50
 
 
51
 
mg::DisplayConfigurationMode conf_mode_from_drm_mode(drmModeModeInfo const& mode)
52
 
{
53
 
    geom::Size const size{mode.hdisplay, mode.vdisplay};
54
 
    double vrefresh_hz{0.0};
55
 
 
56
 
    /* Calculate vertical refresh rate from DRM mode information */
57
 
    if (mode.htotal != 0.0 && mode.vtotal != 0.0)
58
 
    {
59
 
        vrefresh_hz = mode.clock * 1000.0 / (mode.htotal * mode.vtotal);
60
 
        vrefresh_hz = round(vrefresh_hz * 10.0) / 10.0;
61
 
    }
62
 
 
63
 
    return mg::DisplayConfigurationMode{size, vrefresh_hz};
64
 
}
65
 
 
66
 
class GBMDisplayConfigurationTest : public ::testing::Test
67
 
{
68
 
public:
69
 
    GBMDisplayConfigurationTest()
70
 
    {
71
 
        using namespace testing;
72
 
 
73
 
        /* Needed for display start-up */
74
 
        ON_CALL(mock_egl, eglChooseConfig(_,_,_,1,_))
75
 
        .WillByDefault(DoAll(SetArgPointee<2>(mock_egl.fake_configs[0]),
76
 
                             SetArgPointee<4>(1),
77
 
                             Return(EGL_TRUE)));
78
 
 
79
 
        const char* egl_exts = "EGL_KHR_image EGL_KHR_image_base EGL_MESA_drm_image";
80
 
        const char* gl_exts = "GL_OES_texture_npot GL_OES_EGL_image";
81
 
 
82
 
        ON_CALL(mock_egl, eglQueryString(_,EGL_EXTENSIONS))
83
 
        .WillByDefault(Return(egl_exts));
84
 
        ON_CALL(mock_gl, glGetString(GL_EXTENSIONS))
85
 
        .WillByDefault(Return(reinterpret_cast<const GLubyte*>(gl_exts)));
86
 
 
87
 
        setup_sample_modes();
88
 
 
89
 
        fake_devices.add_standard_drm_devices();
90
 
    }
91
 
 
92
 
    std::shared_ptr<mgg::GBMPlatform> create_platform()
93
 
    {
94
 
        return std::make_shared<mgg::GBMPlatform>(
95
 
            std::make_shared<mg::NullDisplayReport>(),
96
 
            std::make_shared<mtd::NullVirtualTerminal>());
97
 
    }
98
 
 
99
 
    std::shared_ptr<mg::Display> create_display(
100
 
        std::shared_ptr<mg::Platform> const& platform)
101
 
    {
102
 
        auto conf_policy = std::make_shared<mg::DefaultDisplayConfigurationPolicy>();
103
 
        return platform->create_display(conf_policy);
104
 
    }
105
 
 
106
 
    void setup_sample_modes()
107
 
    {
108
 
        using fake = mtd::FakeDRMResources;
109
 
 
110
 
        /* Add DRM modes */
111
 
        modes0.push_back(fake::create_mode(1920, 1080, 138500, 2080, 1111, fake::NormalMode));
112
 
        modes0.push_back(fake::create_mode(1920, 1080, 148500, 2200, 1125, fake::PreferredMode));
113
 
        modes0.push_back(fake::create_mode(1680, 1050, 119000, 1840, 1080, fake::NormalMode));
114
 
        modes0.push_back(fake::create_mode(832, 624, 57284, 1152, 667, fake::NormalMode));
115
 
 
116
 
        /* Add the DisplayConfiguration modes corresponding to the DRM modes */
117
 
        for (auto const& mode : modes0)
118
 
            conf_modes0.push_back(conf_mode_from_drm_mode(mode));
119
 
    }
120
 
 
121
 
    ::testing::NiceMock<mtd::MockEGL> mock_egl;
122
 
    ::testing::NiceMock<mtd::MockGL> mock_gl;
123
 
    ::testing::NiceMock<mtd::MockDRM> mock_drm;
124
 
    ::testing::NiceMock<mtd::MockGBM> mock_gbm;
125
 
 
126
 
    std::vector<drmModeModeInfo> modes0;
127
 
    std::vector<mg::DisplayConfigurationMode> conf_modes0;
128
 
    std::vector<drmModeModeInfo> modes_empty;
129
 
 
130
 
    mtf::UdevEnvironment fake_devices;
131
 
};
132
 
 
133
 
}
134
 
 
135
 
TEST_F(GBMDisplayConfigurationTest, configuration_is_read_correctly)
136
 
{
137
 
    using namespace ::testing;
138
 
 
139
 
    /* Set up DRM resources */
140
 
    uint32_t const invalid_id{0};
141
 
    uint32_t const crtc0_id{10};
142
 
    uint32_t const encoder0_id{20};
143
 
    uint32_t const encoder1_id{21};
144
 
    uint32_t const connector0_id{30};
145
 
    uint32_t const connector1_id{31};
146
 
    uint32_t const connector2_id{32};
147
 
    geom::Size const connector0_physical_size_mm{480, 270};
148
 
    geom::Size const connector1_physical_size_mm{};
149
 
    geom::Size const connector2_physical_size_mm{};
150
 
    std::vector<uint32_t> possible_encoder_ids_empty;
151
 
    uint32_t const possible_crtcs_mask_empty{0};
152
 
    size_t const max_simultaneous_outputs{1};
153
 
 
154
 
    mtd::FakeDRMResources& resources(mock_drm.fake_drm);
155
 
 
156
 
    resources.reset();
157
 
 
158
 
    resources.add_crtc(crtc0_id, modes0[1]);
159
 
 
160
 
    resources.add_encoder(encoder0_id, crtc0_id, possible_crtcs_mask_empty);
161
 
    resources.add_encoder(encoder1_id, invalid_id, possible_crtcs_mask_empty);
162
 
 
163
 
    resources.add_connector(connector0_id, DRM_MODE_CONNECTOR_HDMIA,
164
 
                            DRM_MODE_CONNECTED, encoder0_id,
165
 
                            modes0, possible_encoder_ids_empty,
166
 
                            connector0_physical_size_mm);
167
 
    resources.add_connector(connector1_id, DRM_MODE_CONNECTOR_Unknown,
168
 
                            DRM_MODE_DISCONNECTED, invalid_id,
169
 
                            modes_empty, possible_encoder_ids_empty,
170
 
                            connector1_physical_size_mm);
171
 
    resources.add_connector(connector2_id, DRM_MODE_CONNECTOR_eDP,
172
 
                            DRM_MODE_DISCONNECTED, encoder1_id,
173
 
                            modes_empty, possible_encoder_ids_empty,
174
 
                            connector2_physical_size_mm);
175
 
 
176
 
    resources.prepare();
177
 
 
178
 
    /* Expected results */
179
 
    std::vector<mg::DisplayConfigurationCard> const expected_cards =
180
 
    {
181
 
        {
182
 
            mg::DisplayConfigurationCardId{0},
183
 
            max_simultaneous_outputs
184
 
        }
185
 
    };
186
 
 
187
 
    std::vector<mg::DisplayConfigurationOutput> const expected_outputs =
188
 
    {
189
 
        {
190
 
            mg::DisplayConfigurationOutputId{connector0_id},
191
 
            mg::DisplayConfigurationCardId{0},
192
 
            mg::DisplayConfigurationOutputType::hdmia,
193
 
            {},
194
 
            conf_modes0,
195
 
            1,
196
 
            connector0_physical_size_mm,
197
 
            true,
198
 
            true,
199
 
            geom::Point(),
200
 
            1,
201
 
            0,
202
 
            mir_power_mode_on
203
 
        },
204
 
        {
205
 
            mg::DisplayConfigurationOutputId{connector1_id},
206
 
            mg::DisplayConfigurationCardId{0},
207
 
            mg::DisplayConfigurationOutputType::unknown,
208
 
            {},
209
 
            std::vector<mg::DisplayConfigurationMode>(),
210
 
            std::numeric_limits<size_t>::max(),
211
 
            connector1_physical_size_mm,
212
 
            false,
213
 
            false,
214
 
            geom::Point(),
215
 
            std::numeric_limits<size_t>::max(),
216
 
            std::numeric_limits<size_t>::max(),
217
 
            mir_power_mode_on
218
 
        },
219
 
        {
220
 
            mg::DisplayConfigurationOutputId{connector2_id},
221
 
            mg::DisplayConfigurationCardId{0},
222
 
            mg::DisplayConfigurationOutputType::edp,
223
 
            {},
224
 
            std::vector<mg::DisplayConfigurationMode>(),
225
 
            std::numeric_limits<size_t>::max(),
226
 
            connector2_physical_size_mm,
227
 
            false,
228
 
            false,
229
 
            geom::Point(),
230
 
            std::numeric_limits<size_t>::max(),
231
 
            std::numeric_limits<size_t>::max(),
232
 
            mir_power_mode_on
233
 
        }
234
 
    };
235
 
 
236
 
    /* Test body */
237
 
    auto display = create_display(create_platform());
238
 
 
239
 
    auto conf = display->configuration();
240
 
 
241
 
    size_t card_count{0};
242
 
 
243
 
    conf->for_each_card([&](mg::DisplayConfigurationCard const& card)
244
 
    {
245
 
        ASSERT_LT(card_count, expected_cards.size());
246
 
        EXPECT_EQ(expected_cards[card_count], card) << "card_count: " << card_count;
247
 
        ++card_count;
248
 
    });
249
 
 
250
 
    size_t output_count{0};
251
 
 
252
 
    conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
253
 
    {
254
 
        ASSERT_LT(output_count, expected_outputs.size());
255
 
        EXPECT_EQ(expected_outputs[output_count], output) << "output_count: " << output_count;
256
 
        ++output_count;
257
 
    });
258
 
 
259
 
    EXPECT_EQ(expected_outputs.size(), output_count);
260
 
}
261
 
 
262
 
TEST_F(GBMDisplayConfigurationTest, get_kms_connector_id_returns_correct_id)
263
 
{
264
 
    uint32_t const crtc0_id{10};
265
 
    uint32_t const encoder0_id{20};
266
 
    uint32_t const possible_crtcs_mask_empty{0};
267
 
    std::vector<uint32_t> const connector_ids{30, 31};
268
 
    std::vector<uint32_t> encoder_ids{20};
269
 
 
270
 
    /* Set up DRM resources */
271
 
    mtd::FakeDRMResources& resources(mock_drm.fake_drm);
272
 
 
273
 
    resources.reset();
274
 
 
275
 
    resources.add_crtc(crtc0_id, modes0[1]);
276
 
    resources.add_encoder(encoder0_id, crtc0_id, possible_crtcs_mask_empty);
277
 
    for (auto id : connector_ids)
278
 
    {
279
 
        resources.add_connector(id, DRM_MODE_CONNECTOR_DVID,
280
 
                                DRM_MODE_CONNECTED, encoder0_id,
281
 
                                modes0, encoder_ids,
282
 
                                geom::Size());
283
 
    }
284
 
 
285
 
    resources.prepare();
286
 
 
287
 
    /* Test body */
288
 
    auto display = create_display(create_platform());
289
 
 
290
 
    auto conf = display->configuration();
291
 
    auto const& kms_conf = std::static_pointer_cast<mgg::KMSDisplayConfiguration>(conf);
292
 
 
293
 
    size_t output_count{0};
294
 
 
295
 
    conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
296
 
    {
297
 
        ASSERT_LT(output_count, connector_ids.size());
298
 
 
299
 
        EXPECT_EQ(connector_ids[output_count],
300
 
                  kms_conf->get_kms_connector_id(output.id));
301
 
        ++output_count;
302
 
    });
303
 
}
304
 
 
305
 
TEST_F(GBMDisplayConfigurationTest, get_kms_connector_id_throws_on_invalid_id)
306
 
{
307
 
    uint32_t const crtc0_id{10};
308
 
    uint32_t const encoder0_id{20};
309
 
    uint32_t const possible_crtcs_mask_empty{0};
310
 
    std::vector<uint32_t> const connector_ids{30, 31};
311
 
    std::vector<uint32_t> encoder_ids{20};
312
 
 
313
 
    /* Set up DRM resources */
314
 
    mtd::FakeDRMResources& resources(mock_drm.fake_drm);
315
 
 
316
 
    resources.reset();
317
 
 
318
 
    resources.add_crtc(crtc0_id, modes0[1]);
319
 
    resources.add_encoder(encoder0_id, crtc0_id, possible_crtcs_mask_empty);
320
 
    for (auto id : connector_ids)
321
 
    {
322
 
        resources.add_connector(id, DRM_MODE_CONNECTOR_VGA,
323
 
                                DRM_MODE_CONNECTED, encoder0_id,
324
 
                                modes0, encoder_ids,
325
 
                                geom::Size());
326
 
    }
327
 
 
328
 
    resources.prepare();
329
 
 
330
 
    /* Test body */
331
 
    auto display = create_display(create_platform());
332
 
 
333
 
    auto conf = display->configuration();
334
 
    auto const& kms_conf = std::static_pointer_cast<mgg::KMSDisplayConfiguration>(conf);
335
 
 
336
 
    EXPECT_THROW({
337
 
        kms_conf->get_kms_connector_id(mg::DisplayConfigurationOutputId{29});
338
 
    }, std::runtime_error);
339
 
    EXPECT_THROW({
340
 
        kms_conf->get_kms_connector_id(mg::DisplayConfigurationOutputId{32});
341
 
    }, std::runtime_error);
342
 
}
343
 
 
344
 
TEST_F(GBMDisplayConfigurationTest, returns_updated_configuration)
345
 
{
346
 
    using namespace ::testing;
347
 
 
348
 
    uint32_t const invalid_id{0};
349
 
    std::vector<uint32_t> const crtc_ids{10, 11};
350
 
    std::vector<uint32_t> const encoder_ids{20, 21};
351
 
    std::vector<uint32_t> const connector_ids{30, 31};
352
 
    std::vector<geom::Size> const connector_physical_sizes_mm_before{
353
 
        {480, 270}, {}
354
 
    };
355
 
    std::vector<geom::Size> const connector_physical_sizes_mm_after{
356
 
        {}, {512, 642}
357
 
    };
358
 
    std::vector<uint32_t> possible_encoder_ids_empty;
359
 
    uint32_t const possible_crtcs_mask_empty{0};
360
 
    size_t const max_simultaneous_outputs{1};
361
 
 
362
 
    /* Expected results */
363
 
    std::vector<mg::DisplayConfigurationCard> const expected_cards =
364
 
    {
365
 
        {
366
 
            mg::DisplayConfigurationCardId{0},
367
 
            max_simultaneous_outputs
368
 
        }
369
 
    };
370
 
 
371
 
    std::vector<mg::DisplayConfigurationOutput> const expected_outputs_before =
372
 
    {
373
 
        {
374
 
            mg::DisplayConfigurationOutputId(connector_ids[0]),
375
 
            mg::DisplayConfigurationCardId{0},
376
 
            mg::DisplayConfigurationOutputType::composite,
377
 
            {},
378
 
            conf_modes0,
379
 
            1,
380
 
            connector_physical_sizes_mm_before[0],
381
 
            true,
382
 
            true,
383
 
            geom::Point(),
384
 
            1,
385
 
            0,
386
 
            mir_power_mode_on
387
 
        },
388
 
        {
389
 
            mg::DisplayConfigurationOutputId(connector_ids[1]),
390
 
            mg::DisplayConfigurationCardId{0},
391
 
            mg::DisplayConfigurationOutputType::vga,
392
 
            {},
393
 
            std::vector<mg::DisplayConfigurationMode>(),
394
 
            std::numeric_limits<size_t>::max(),
395
 
            connector_physical_sizes_mm_before[1],
396
 
            false,
397
 
            false,
398
 
            geom::Point(),
399
 
            std::numeric_limits<size_t>::max(),
400
 
            std::numeric_limits<size_t>::max(),
401
 
            mir_power_mode_on
402
 
        },
403
 
    };
404
 
 
405
 
    std::vector<mg::DisplayConfigurationOutput> const expected_outputs_after =
406
 
    {
407
 
        {
408
 
            mg::DisplayConfigurationOutputId(connector_ids[0]),
409
 
            mg::DisplayConfigurationCardId{0},
410
 
            mg::DisplayConfigurationOutputType::composite,
411
 
            {},
412
 
            std::vector<mg::DisplayConfigurationMode>(),
413
 
            std::numeric_limits<size_t>::max(),
414
 
            connector_physical_sizes_mm_after[0],
415
 
            false,
416
 
            true,
417
 
            geom::Point(),
418
 
            std::numeric_limits<size_t>::max(),
419
 
            std::numeric_limits<size_t>::max(),
420
 
            mir_power_mode_on
421
 
        },
422
 
        {
423
 
            mg::DisplayConfigurationOutputId(connector_ids[1]),
424
 
            mg::DisplayConfigurationCardId{0},
425
 
            mg::DisplayConfigurationOutputType::vga,
426
 
            {},
427
 
            conf_modes0,
428
 
            1,
429
 
            connector_physical_sizes_mm_after[1],
430
 
            true,
431
 
            false,
432
 
            geom::Point(),
433
 
            1,
434
 
            0,
435
 
            mir_power_mode_on
436
 
        },
437
 
    };
438
 
 
439
 
    /* Set up DRM resources and check */
440
 
    mtd::FakeDRMResources& resources(mock_drm.fake_drm);
441
 
 
442
 
    resources.reset();
443
 
 
444
 
    resources.add_crtc(crtc_ids[0], modes0[1]);
445
 
 
446
 
    resources.add_encoder(encoder_ids[0], crtc_ids[0], possible_crtcs_mask_empty);
447
 
    resources.add_encoder(encoder_ids[1], invalid_id, possible_crtcs_mask_empty);
448
 
 
449
 
    resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_Composite,
450
 
                            DRM_MODE_CONNECTED, encoder_ids[0],
451
 
                            modes0, possible_encoder_ids_empty,
452
 
                            connector_physical_sizes_mm_before[0]);
453
 
    resources.add_connector(connector_ids[1], DRM_MODE_CONNECTOR_VGA,
454
 
                            DRM_MODE_DISCONNECTED, invalid_id,
455
 
                            modes_empty, possible_encoder_ids_empty,
456
 
                            connector_physical_sizes_mm_before[1]);
457
 
 
458
 
    resources.prepare();
459
 
 
460
 
    auto display = create_display(create_platform());
461
 
 
462
 
    auto conf = display->configuration();
463
 
 
464
 
    size_t card_count{0};
465
 
 
466
 
    conf->for_each_card([&](mg::DisplayConfigurationCard const& card)
467
 
    {
468
 
        ASSERT_LT(card_count, expected_cards.size());
469
 
        EXPECT_EQ(expected_cards[card_count], card) << "card_count: " << card_count;
470
 
        ++card_count;
471
 
    });
472
 
 
473
 
    size_t output_count{0};
474
 
 
475
 
    conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
476
 
    {
477
 
        ASSERT_LT(output_count, expected_outputs_before.size());
478
 
        EXPECT_EQ(expected_outputs_before[output_count], output) << "output_count: " << output_count;
479
 
        ++output_count;
480
 
    });
481
 
 
482
 
    EXPECT_EQ(expected_outputs_before.size(), output_count);
483
 
 
484
 
    /* Reset DRM resources and check again */
485
 
    resources.reset();
486
 
 
487
 
    resources.add_crtc(crtc_ids[1], modes0[1]);
488
 
 
489
 
    resources.add_encoder(encoder_ids[0], invalid_id, possible_crtcs_mask_empty);
490
 
    resources.add_encoder(encoder_ids[1], crtc_ids[1], possible_crtcs_mask_empty);
491
 
 
492
 
    resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_Composite,
493
 
                            DRM_MODE_DISCONNECTED, invalid_id,
494
 
                            modes_empty, possible_encoder_ids_empty,
495
 
                            connector_physical_sizes_mm_after[0]);
496
 
    resources.add_connector(connector_ids[1], DRM_MODE_CONNECTOR_VGA,
497
 
                            DRM_MODE_CONNECTED, encoder_ids[1],
498
 
                            modes0, possible_encoder_ids_empty,
499
 
                            connector_physical_sizes_mm_after[1]);
500
 
 
501
 
    resources.prepare();
502
 
 
503
 
    conf = display->configuration();
504
 
 
505
 
    card_count = 0;
506
 
 
507
 
    conf->for_each_card([&](mg::DisplayConfigurationCard const& card)
508
 
    {
509
 
        ASSERT_LT(card_count, expected_cards.size());
510
 
        EXPECT_EQ(expected_cards[card_count], card) << "card_count: " << card_count;
511
 
        ++card_count;
512
 
    });
513
 
 
514
 
    output_count = 0;
515
 
 
516
 
    conf->for_each_output([&](mg::DisplayConfigurationOutput const& output)
517
 
    {
518
 
        ASSERT_LT(output_count, expected_outputs_after.size());
519
 
        EXPECT_EQ(expected_outputs_after[output_count], output) << "output_count: " << output_count;
520
 
        ++output_count;
521
 
    });
522
 
 
523
 
    EXPECT_EQ(expected_outputs_after.size(), output_count);
524
 
}