~ubuntu-branches/ubuntu/vivid/mir/vivid

« back to all changes in this revision

Viewing changes to tests/unit-tests/graphics/gbm/test_real_kms_output.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 "src/server/graphics/gbm/real_kms_output.h"
20
 
#include "src/server/graphics/gbm/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 mgg = mir::graphics::gbm;
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 mgg::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 mgg::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
 
    mgg::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
 
    mgg::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
 
    mgg::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
 
    mgg::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
 
    mgg::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
 
    mgg::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
 
    mgg::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
 
}