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

« back to all changes in this revision

Viewing changes to tests/unit-tests/graphics/mesa/test_cursor.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/cursor.h"
 
20
#include "src/platform/graphics/mesa/kms_output.h"
 
21
#include "src/platform/graphics/mesa/kms_output_container.h"
 
22
#include "src/platform/graphics/mesa/kms_display_configuration.h"
 
23
 
 
24
#include "mir_test_doubles/mock_gbm.h"
 
25
 
 
26
#include <gtest/gtest.h>
 
27
#include <gmock/gmock.h>
 
28
 
 
29
#include <unordered_map>
 
30
 
 
31
namespace mg = mir::graphics;
 
32
namespace mgm = mir::graphics::mesa;
 
33
namespace geom = mir::geometry;
 
34
namespace mtd = mir::test::doubles;
 
35
 
 
36
namespace
 
37
{
 
38
 
 
39
struct MockKMSOutput : public mgm::KMSOutput
 
40
{
 
41
    MOCK_METHOD0(reset, void());
 
42
    MOCK_METHOD2(configure, void(geom::Displacement, size_t));
 
43
    MOCK_CONST_METHOD0(size, geom::Size());
 
44
 
 
45
    MOCK_METHOD1(set_crtc, bool(uint32_t));
 
46
    MOCK_METHOD0(clear_crtc, void());
 
47
    MOCK_METHOD1(schedule_page_flip, bool(uint32_t));
 
48
    MOCK_METHOD0(wait_for_page_flip, void());
 
49
 
 
50
    MOCK_METHOD1(set_cursor, void(gbm_bo*));
 
51
    MOCK_METHOD1(move_cursor, void(geom::Point));
 
52
    MOCK_METHOD0(clear_cursor, void());
 
53
    MOCK_CONST_METHOD0(has_cursor, bool());
 
54
 
 
55
    MOCK_METHOD1(set_power_mode, void(MirPowerMode));
 
56
};
 
57
 
 
58
struct StubKMSOutputContainer : public mgm::KMSOutputContainer
 
59
{
 
60
    StubKMSOutputContainer()
 
61
        : outputs{
 
62
            {10, std::make_shared<testing::NiceMock<MockKMSOutput>>()},
 
63
            {11, std::make_shared<testing::NiceMock<MockKMSOutput>>()}}
 
64
    {
 
65
    }
 
66
 
 
67
    std::shared_ptr<mgm::KMSOutput> get_kms_output_for(uint32_t connector_id)
 
68
    {
 
69
        return outputs[connector_id];
 
70
    }
 
71
 
 
72
    void for_each_output(std::function<void(mgm::KMSOutput&)> functor) const
 
73
    {
 
74
        for (auto const& pair : outputs)
 
75
            functor(*pair.second);
 
76
    }
 
77
 
 
78
    void verify_and_clear_expectations()
 
79
    {
 
80
        for (auto const& pair : outputs)
 
81
            ::testing::Mock::VerifyAndClearExpectations(pair.second.get());
 
82
    }
 
83
 
 
84
    std::unordered_map<uint32_t,std::shared_ptr<testing::NiceMock<MockKMSOutput>>> outputs;
 
85
};
 
86
 
 
87
struct StubKMSDisplayConfiguration : public mgm::KMSDisplayConfiguration
 
88
{
 
89
    StubKMSDisplayConfiguration()
 
90
        : card_id{1}
 
91
    {
 
92
        outputs.push_back(
 
93
            {
 
94
                mg::DisplayConfigurationOutputId{10},
 
95
                card_id,
 
96
                mg::DisplayConfigurationOutputType::vga,
 
97
                {},
 
98
                {
 
99
                    {geom::Size{10, 20}, 59.9},
 
100
                    {geom::Size{200, 100}, 59.9},
 
101
                },
 
102
                1,
 
103
                geom::Size{324, 642},
 
104
                true,
 
105
                true,
 
106
                geom::Point{0, 0},
 
107
                1,
 
108
                0,
 
109
                mir_power_mode_on
 
110
            });
 
111
        outputs.push_back(
 
112
            {
 
113
                mg::DisplayConfigurationOutputId{11},
 
114
                card_id,
 
115
                mg::DisplayConfigurationOutputType::vga,
 
116
                {},
 
117
                {
 
118
                    {geom::Size{200, 200}, 59.9},
 
119
                    {geom::Size{100, 200}, 59.9},
 
120
                },
 
121
                0,
 
122
                geom::Size{566, 111},
 
123
                true,
 
124
                true,
 
125
                geom::Point{100, 50},
 
126
                0,
 
127
                0,
 
128
                mir_power_mode_on
 
129
            });
 
130
    }
 
131
 
 
132
    void for_each_card(std::function<void(mg::DisplayConfigurationCard const&)> f) const
 
133
    {
 
134
        f({card_id, outputs.size()});
 
135
    }
 
136
 
 
137
    void for_each_output(std::function<void(mg::DisplayConfigurationOutput const&)> f) const
 
138
    {
 
139
        for (auto const& output : outputs)
 
140
            f(output);
 
141
    }
 
142
 
 
143
    void configure_output(mg::DisplayConfigurationOutputId, bool,
 
144
                          geom::Point, size_t, MirPowerMode)
 
145
    {
 
146
    }
 
147
 
 
148
    uint32_t get_kms_connector_id(mg::DisplayConfigurationOutputId id) const
 
149
    {
 
150
        return id.as_value();
 
151
    }
 
152
 
 
153
    size_t get_kms_mode_index(mg::DisplayConfigurationOutputId, size_t conf_mode_index) const
 
154
    {
 
155
        return conf_mode_index;
 
156
    }
 
157
 
 
158
    void update()
 
159
    {
 
160
    }
 
161
 
 
162
    mg::DisplayConfigurationCardId card_id;
 
163
    std::vector<mg::DisplayConfigurationOutput> outputs;
 
164
};
 
165
 
 
166
struct StubCurrentConfiguration : public mgm::CurrentConfiguration
 
167
{
 
168
    void with_current_configuration_do(
 
169
        std::function<void(mgm::KMSDisplayConfiguration const&)> const& exec)
 
170
    {
 
171
        exec(conf);
 
172
    }
 
173
 
 
174
    StubKMSDisplayConfiguration conf;
 
175
};
 
176
 
 
177
struct MesaCursorTest : public ::testing::Test
 
178
{
 
179
    MesaCursorTest()
 
180
        : cursor{mock_gbm.fake_gbm.device, output_container,
 
181
                 std::make_shared<StubCurrentConfiguration>()}
 
182
    {
 
183
    }
 
184
 
 
185
    testing::NiceMock<mtd::MockGBM> mock_gbm;
 
186
    StubKMSOutputContainer output_container;
 
187
    mgm::Cursor cursor;
 
188
};
 
189
 
 
190
}
 
191
 
 
192
TEST_F(MesaCursorTest, creates_cursor_bo_image)
 
193
{
 
194
    size_t const cursor_side{64};
 
195
    EXPECT_CALL(mock_gbm, gbm_bo_create(mock_gbm.fake_gbm.device,
 
196
                                        cursor_side, cursor_side,
 
197
                                        GBM_FORMAT_ARGB8888,
 
198
                                        GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE));
 
199
 
 
200
    mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
 
201
                              std::make_shared<StubCurrentConfiguration>()};
 
202
}
 
203
 
 
204
TEST_F(MesaCursorTest, set_cursor_writes_to_bo)
 
205
{
 
206
    using namespace testing;
 
207
 
 
208
    void* const image{reinterpret_cast<void*>(0x5678)};
 
209
    size_t const cursor_side{64};
 
210
    geom::Size const cursor_size{cursor_side, cursor_side};
 
211
    size_t const cursor_size_bytes{cursor_side * cursor_side * sizeof(uint32_t)};
 
212
 
 
213
    EXPECT_CALL(mock_gbm, gbm_bo_write(mock_gbm.fake_gbm.bo, image, cursor_size_bytes));
 
214
 
 
215
    cursor.set_image(image, cursor_size);
 
216
}
 
217
 
 
218
TEST_F(MesaCursorTest, set_cursor_throws_on_incorrect_size)
 
219
{
 
220
    using namespace testing;
 
221
 
 
222
    void* const image{reinterpret_cast<void*>(0x5678)};
 
223
    size_t const cursor_side{48};
 
224
    geom::Size const cursor_size{cursor_side, cursor_side};
 
225
 
 
226
    EXPECT_THROW(
 
227
        cursor.set_image(image, cursor_size);
 
228
    , std::logic_error);
 
229
}
 
230
 
 
231
TEST_F(MesaCursorTest, forces_cursor_state_on_construction)
 
232
{
 
233
    using namespace testing;
 
234
 
 
235
    EXPECT_CALL(*output_container.outputs[10], move_cursor(geom::Point{0,0}));
 
236
    EXPECT_CALL(*output_container.outputs[10], set_cursor(_));
 
237
    EXPECT_CALL(*output_container.outputs[11], clear_cursor());
 
238
 
 
239
    /* No checking of existing cursor state */
 
240
    EXPECT_CALL(*output_container.outputs[10], has_cursor()).Times(0);
 
241
    EXPECT_CALL(*output_container.outputs[11], has_cursor()).Times(0);
 
242
 
 
243
    mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
 
244
                              std::make_shared<StubCurrentConfiguration>()};
 
245
 
 
246
    output_container.verify_and_clear_expectations();
 
247
}
 
248
 
 
249
 
 
250
TEST_F(MesaCursorTest, move_to_sets_clears_cursor_if_needed)
 
251
{
 
252
    using namespace testing;
 
253
 
 
254
    EXPECT_CALL(*output_container.outputs[10], has_cursor())
 
255
        .WillOnce(Return(false));
 
256
    EXPECT_CALL(*output_container.outputs[10], set_cursor(_));
 
257
 
 
258
    EXPECT_CALL(*output_container.outputs[11], has_cursor())
 
259
        .WillOnce(Return(true));
 
260
    EXPECT_CALL(*output_container.outputs[11], clear_cursor());
 
261
 
 
262
    cursor.move_to({10, 10});
 
263
 
 
264
    output_container.verify_and_clear_expectations();
 
265
}
 
266
 
 
267
TEST_F(MesaCursorTest, move_to_doesnt_set_clear_cursor_if_not_needed)
 
268
{
 
269
    using namespace testing;
 
270
 
 
271
    EXPECT_CALL(*output_container.outputs[10], has_cursor())
 
272
        .WillOnce(Return(true));
 
273
    EXPECT_CALL(*output_container.outputs[10], set_cursor(_))
 
274
        .Times(0);
 
275
 
 
276
    EXPECT_CALL(*output_container.outputs[11], has_cursor())
 
277
        .WillOnce(Return(false));
 
278
    EXPECT_CALL(*output_container.outputs[11], clear_cursor())
 
279
        .Times(0);
 
280
 
 
281
    cursor.move_to({10, 10});
 
282
 
 
283
    output_container.verify_and_clear_expectations();
 
284
}
 
285
 
 
286
TEST_F(MesaCursorTest, move_to_moves_cursor_to_right_output)
 
287
{
 
288
    using namespace testing;
 
289
 
 
290
    EXPECT_CALL(*output_container.outputs[10], move_cursor(geom::Point{10,10}));
 
291
    EXPECT_CALL(*output_container.outputs[11], move_cursor(_))
 
292
        .Times(0);
 
293
 
 
294
    cursor.move_to({10, 10});
 
295
 
 
296
    output_container.verify_and_clear_expectations();
 
297
 
 
298
    EXPECT_CALL(*output_container.outputs[10], move_cursor(_))
 
299
        .Times(0);
 
300
    EXPECT_CALL(*output_container.outputs[11], move_cursor(geom::Point{50,100}));
 
301
 
 
302
    cursor.move_to({150, 150});
 
303
 
 
304
    output_container.verify_and_clear_expectations();
 
305
 
 
306
    EXPECT_CALL(*output_container.outputs[10], move_cursor(geom::Point{150,75}));
 
307
    EXPECT_CALL(*output_container.outputs[11], move_cursor(geom::Point{50,25}));
 
308
 
 
309
    cursor.move_to({150, 75});
 
310
 
 
311
    output_container.verify_and_clear_expectations();
 
312
 
 
313
    EXPECT_CALL(*output_container.outputs[10], move_cursor(_))
 
314
        .Times(0);
 
315
    EXPECT_CALL(*output_container.outputs[11], move_cursor(_))
 
316
        .Times(0);
 
317
 
 
318
    cursor.move_to({-1, -1});
 
319
 
 
320
    output_container.verify_and_clear_expectations();
 
321
}
 
322
 
 
323
TEST_F(MesaCursorTest, shows_at_last_known_position)
 
324
{
 
325
    using namespace testing;
 
326
 
 
327
    EXPECT_CALL(*output_container.outputs[10], move_cursor(geom::Point{150,75}));
 
328
    EXPECT_CALL(*output_container.outputs[11], move_cursor(geom::Point{50,25}));
 
329
 
 
330
    cursor.move_to({150, 75});
 
331
 
 
332
    output_container.verify_and_clear_expectations();
 
333
 
 
334
    EXPECT_CALL(*output_container.outputs[10], move_cursor(geom::Point{150,75}));
 
335
    EXPECT_CALL(*output_container.outputs[11], move_cursor(geom::Point{50,25}));
 
336
 
 
337
    cursor.show_at_last_known_position();
 
338
 
 
339
    output_container.verify_and_clear_expectations();
 
340
}
 
341
 
 
342
TEST_F(MesaCursorTest, hides_cursor_in_all_outputs)
 
343
{
 
344
    using namespace testing;
 
345
 
 
346
    EXPECT_CALL(*output_container.outputs[10], clear_cursor());
 
347
    EXPECT_CALL(*output_container.outputs[11], clear_cursor());
 
348
 
 
349
    cursor.hide();
 
350
 
 
351
    output_container.verify_and_clear_expectations();
 
352
}
 
353
 
 
354
TEST_F(MesaCursorTest, clears_cursor_on_exit)
 
355
{
 
356
    using namespace testing;
 
357
 
 
358
    EXPECT_CALL(*output_container.outputs[10], clear_cursor());
 
359
    EXPECT_CALL(*output_container.outputs[11], clear_cursor());
 
360
}