~hikiko/mir/mir.unity8-desktop-session

« back to all changes in this revision

Viewing changes to tests/unit-tests/graphics/mesa/test_real_kms_output.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Daniel van Vugt, Ubuntu daily release
  • Date: 2014-01-08 02:04:38 UTC
  • mfrom: (1.1.54)
  • Revision ID: package-import@ubuntu.com-20140108020438-ikbu7qqm9v2l026y
Tags: 0.1.3+14.04.20140108-0ubuntu1
[ Daniel van Vugt ]
* Preparing for release 0.1.3

[ Ubuntu daily release ]
* Automatic snapshot from revision 1170

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 "src/platform/graphics/mesa/real_kms_output.h"
 
20
#include "src/platform/graphics/mesa/page_flipper.h"
 
21
 
 
22
#include "mir_test/fake_shared.h"
 
23
 
 
24
#include "mir_test_doubles/mock_drm.h"
 
25
 
 
26
#include <stdexcept>
 
27
 
 
28
#include <gtest/gtest.h>
 
29
#include <gmock/gmock.h>
 
30
 
 
31
namespace mg = mir::graphics;
 
32
namespace mgm = mir::graphics::mesa;
 
33
namespace geom = mir::geometry;
 
34
namespace mt = mir::test;
 
35
namespace mtd = mir::test::doubles;
 
36
 
 
37
namespace
 
38
{
 
39
 
 
40
class NullPageFlipper : public mgm::PageFlipper
 
41
{
 
42
public:
 
43
    bool schedule_flip(uint32_t,uint32_t) { return true; }
 
44
    void wait_for_flip(uint32_t) { }
 
45
};
 
46
 
 
47
class MockPageFlipper : public mgm::PageFlipper
 
48
{
 
49
public:
 
50
    MOCK_METHOD2(schedule_flip, bool(uint32_t,uint32_t));
 
51
    MOCK_METHOD1(wait_for_flip, void(uint32_t));
 
52
};
 
53
 
 
54
class RealKMSOutputTest : public ::testing::Test
 
55
{
 
56
public:
 
57
    RealKMSOutputTest()
 
58
        : invalid_id{0}, crtc_ids{10, 11},
 
59
          encoder_ids{20, 21}, connector_ids{30, 21},
 
60
          possible_encoder_ids1{encoder_ids[0]},
 
61
          possible_encoder_ids2{encoder_ids[0], encoder_ids[1]}
 
62
    {
 
63
    }
 
64
 
 
65
    void setup_outputs_connected_crtc()
 
66
    {
 
67
        mtd::FakeDRMResources& resources(mock_drm.fake_drm);
 
68
        uint32_t const possible_crtcs_mask{0x1};
 
69
 
 
70
        resources.reset();
 
71
 
 
72
        resources.add_crtc(crtc_ids[0], drmModeModeInfo());
 
73
        resources.add_encoder(encoder_ids[0], crtc_ids[0], possible_crtcs_mask);
 
74
        resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_VGA,
 
75
                                DRM_MODE_CONNECTED, encoder_ids[0],
 
76
                                modes_empty, possible_encoder_ids1, geom::Size());
 
77
 
 
78
        resources.prepare();
 
79
    }
 
80
 
 
81
    void setup_outputs_no_connected_crtc()
 
82
    {
 
83
        mtd::FakeDRMResources& resources(mock_drm.fake_drm);
 
84
        uint32_t const possible_crtcs_mask1{0x1};
 
85
        uint32_t const possible_crtcs_mask_all{0x3};
 
86
 
 
87
        resources.reset();
 
88
 
 
89
        resources.add_crtc(crtc_ids[0], drmModeModeInfo());
 
90
        resources.add_crtc(crtc_ids[1], drmModeModeInfo());
 
91
        resources.add_encoder(encoder_ids[0], crtc_ids[0], possible_crtcs_mask1);
 
92
        resources.add_encoder(encoder_ids[1], invalid_id, possible_crtcs_mask_all);
 
93
        resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_Composite,
 
94
                                DRM_MODE_CONNECTED, invalid_id,
 
95
                                modes_empty, possible_encoder_ids2, geom::Size());
 
96
        resources.add_connector(connector_ids[1], DRM_MODE_CONNECTOR_DVIA,
 
97
                                DRM_MODE_CONNECTED, encoder_ids[0],
 
98
                                modes_empty, possible_encoder_ids2, geom::Size());
 
99
 
 
100
        resources.prepare();
 
101
    }
 
102
 
 
103
    testing::NiceMock<mtd::MockDRM> mock_drm;
 
104
    MockPageFlipper mock_page_flipper;
 
105
    NullPageFlipper null_page_flipper;
 
106
 
 
107
    std::vector<drmModeModeInfo> modes_empty;
 
108
    uint32_t const invalid_id;
 
109
    std::vector<uint32_t> const crtc_ids;
 
110
    std::vector<uint32_t> const encoder_ids;
 
111
    std::vector<uint32_t> const connector_ids;
 
112
    std::vector<uint32_t> possible_encoder_ids1;
 
113
    std::vector<uint32_t> possible_encoder_ids2;
 
114
};
 
115
 
 
116
}
 
117
 
 
118
TEST_F(RealKMSOutputTest, construction_queries_connector)
 
119
{
 
120
    using namespace testing;
 
121
 
 
122
    setup_outputs_connected_crtc();
 
123
 
 
124
    EXPECT_CALL(mock_drm, drmModeGetConnector(_,connector_ids[0]))
 
125
        .Times(1);
 
126
 
 
127
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
128
                              mt::fake_shared(null_page_flipper)};
 
129
}
 
130
 
 
131
TEST_F(RealKMSOutputTest, operations_use_existing_crtc)
 
132
{
 
133
    using namespace testing;
 
134
 
 
135
    uint32_t const fb_id{67};
 
136
 
 
137
    setup_outputs_connected_crtc();
 
138
 
 
139
    {
 
140
        InSequence s;
 
141
 
 
142
        EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], fb_id, _, _,
 
143
                                             Pointee(connector_ids[0]), _, _))
 
144
            .Times(1);
 
145
 
 
146
        EXPECT_CALL(mock_page_flipper, schedule_flip(crtc_ids[0], fb_id))
 
147
            .Times(1)
 
148
            .WillOnce(Return(true));
 
149
 
 
150
        EXPECT_CALL(mock_page_flipper, wait_for_flip(crtc_ids[0]))
 
151
            .Times(1);
 
152
 
 
153
        EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], Ne(fb_id), _, _,
 
154
                                             Pointee(connector_ids[0]), _, _))
 
155
            .Times(1);
 
156
    }
 
157
 
 
158
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
159
                              mt::fake_shared(mock_page_flipper)};
 
160
 
 
161
    EXPECT_TRUE(output.set_crtc(fb_id));
 
162
    EXPECT_TRUE(output.schedule_page_flip(fb_id));
 
163
    output.wait_for_page_flip();
 
164
}
 
165
 
 
166
TEST_F(RealKMSOutputTest, operations_use_possible_crtc)
 
167
{
 
168
    using namespace testing;
 
169
 
 
170
    uint32_t const fb_id{67};
 
171
 
 
172
    setup_outputs_no_connected_crtc();
 
173
 
 
174
    {
 
175
        InSequence s;
 
176
 
 
177
        EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[1], fb_id, _, _,
 
178
                                             Pointee(connector_ids[0]), _, _))
 
179
            .Times(1);
 
180
 
 
181
        EXPECT_CALL(mock_page_flipper, schedule_flip(crtc_ids[1], fb_id))
 
182
            .Times(1)
 
183
            .WillOnce(Return(true));
 
184
 
 
185
        EXPECT_CALL(mock_page_flipper, wait_for_flip(crtc_ids[1]))
 
186
            .Times(1);
 
187
 
 
188
        EXPECT_CALL(mock_drm, drmModeSetCrtc(_, 0, 0, _, _,
 
189
                                             Pointee(connector_ids[0]), _, _))
 
190
            .Times(1);
 
191
    }
 
192
 
 
193
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
194
                              mt::fake_shared(mock_page_flipper)};
 
195
 
 
196
    EXPECT_TRUE(output.set_crtc(fb_id));
 
197
    EXPECT_TRUE(output.schedule_page_flip(fb_id));
 
198
    output.wait_for_page_flip();
 
199
}
 
200
 
 
201
TEST_F(RealKMSOutputTest, set_crtc_failure_is_handled_gracefully)
 
202
{
 
203
    using namespace testing;
 
204
 
 
205
    uint32_t const fb_id{67};
 
206
 
 
207
    setup_outputs_connected_crtc();
 
208
 
 
209
    {
 
210
        InSequence s;
 
211
 
 
212
        EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], fb_id, _, _, _, _, _))
 
213
            .Times(1)
 
214
            .WillOnce(Return(1));
 
215
 
 
216
        EXPECT_CALL(mock_page_flipper, schedule_flip(_, _))
 
217
            .Times(0);
 
218
 
 
219
        EXPECT_CALL(mock_page_flipper, wait_for_flip(_))
 
220
            .Times(0);
 
221
 
 
222
        EXPECT_CALL(mock_drm, drmModeSetCrtc(_, _, _, _, _, _, _, _))
 
223
            .Times(0);
 
224
    }
 
225
 
 
226
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
227
                              mt::fake_shared(mock_page_flipper)};
 
228
 
 
229
    EXPECT_FALSE(output.set_crtc(fb_id));
 
230
    EXPECT_THROW({
 
231
        output.schedule_page_flip(fb_id);
 
232
    }, std::runtime_error);
 
233
    EXPECT_THROW({
 
234
        output.wait_for_page_flip();
 
235
    }, std::runtime_error);
 
236
}
 
237
 
 
238
TEST_F(RealKMSOutputTest, clear_crtc_gets_crtc_if_none_is_current)
 
239
{
 
240
    using namespace testing;
 
241
 
 
242
    setup_outputs_connected_crtc();
 
243
 
 
244
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
245
                              mt::fake_shared(mock_page_flipper)};
 
246
 
 
247
    EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], 0, 0, 0, nullptr, 0, nullptr))
 
248
        .Times(1)
 
249
        .WillOnce(Return(0));
 
250
 
 
251
    output.clear_crtc();
 
252
}
 
253
 
 
254
TEST_F(RealKMSOutputTest, clear_crtc_does_not_throw_if_no_crtc_is_found)
 
255
{
 
256
    using namespace testing;
 
257
 
 
258
    mtd::FakeDRMResources& resources(mock_drm.fake_drm);
 
259
    uint32_t const possible_crtcs_mask_empty{0x0};
 
260
 
 
261
    resources.reset();
 
262
 
 
263
    resources.add_encoder(encoder_ids[0], invalid_id, possible_crtcs_mask_empty);
 
264
    resources.add_connector(connector_ids[0], DRM_MODE_CONNECTOR_VGA,
 
265
                            DRM_MODE_CONNECTED, encoder_ids[0],
 
266
                            modes_empty, possible_encoder_ids1, geom::Size());
 
267
 
 
268
    resources.prepare();
 
269
 
 
270
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
271
                              mt::fake_shared(mock_page_flipper)};
 
272
 
 
273
    EXPECT_CALL(mock_drm, drmModeSetCrtc(_, _, 0, 0, 0, nullptr, 0, nullptr))
 
274
        .Times(0);
 
275
 
 
276
    output.clear_crtc();
 
277
}
 
278
 
 
279
TEST_F(RealKMSOutputTest, clear_crtc_throws_if_drm_call_fails)
 
280
{
 
281
    using namespace testing;
 
282
 
 
283
    setup_outputs_connected_crtc();
 
284
 
 
285
    mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0],
 
286
                              mt::fake_shared(mock_page_flipper)};
 
287
 
 
288
    EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], 0, 0, 0, nullptr, 0, nullptr))
 
289
        .Times(1)
 
290
        .WillOnce(Return(-1));
 
291
 
 
292
    EXPECT_THROW({
 
293
        output.clear_crtc();
 
294
    }, std::runtime_error);
 
295
}