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_toolkit/mir_client_library.h"
20
#include "src/client/gbm/gbm_client_buffer.h"
21
#include "src/client/gbm/gbm_client_buffer_factory.h"
22
#include "mock_drm_fd_handler.h"
26
#include <gtest/gtest.h>
30
namespace geom=mir::geometry;
31
namespace mclg=mir::client::gbm;
33
struct MirGBMBufferTest : public testing::Test
37
width = geom::Width(12);
38
height =geom::Height(14);
39
stride = geom::Stride(66);
40
pf = geom::PixelFormat::abgr_8888;
41
size = geom::Size{width, height};
42
drm_fd_handler = std::make_shared<testing::NiceMock<mclg::MockDRMFDHandler>>();
44
package = std::make_shared<MirBufferPackage>();
45
package->stride = stride.as_uint32_t();
46
package->width = width.as_int();
47
package->height = height.as_int();
49
package_copy = std::make_shared<MirBufferPackage>(*package.get());
57
std::shared_ptr<testing::NiceMock<mclg::MockDRMFDHandler>> drm_fd_handler;
58
std::shared_ptr<MirBufferPackage> package;
59
std::shared_ptr<MirBufferPackage> package_copy;
63
TEST_F(MirGBMBufferTest, width_and_height)
65
using namespace testing;
67
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
69
EXPECT_EQ(buffer.size().height, height);
70
EXPECT_EQ(buffer.size().width, width);
71
EXPECT_EQ(buffer.pixel_format(), pf);
74
TEST_F(MirGBMBufferTest, buffer_returns_correct_stride)
76
using namespace testing;
78
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
80
EXPECT_EQ(buffer.stride(), stride);
83
TEST_F(MirGBMBufferTest, buffer_returns_set_package)
85
using namespace testing;
87
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
89
auto package_return = buffer.native_buffer_handle();
90
EXPECT_EQ(package_return->data_items, package_copy->data_items);
91
EXPECT_EQ(package_return->fd_items, package_copy->fd_items);
92
EXPECT_EQ(package_return->stride, package_copy->stride);
93
for (auto i=0; i<mir_buffer_package_max; i++)
94
EXPECT_EQ(package_return->data[i], package_copy->data[i]);
95
for (auto i=0; i<mir_buffer_package_max; i++)
96
EXPECT_EQ(package_return->fd[i], package_copy->fd[i]);
99
TEST_F(MirGBMBufferTest, secure_for_cpu_write_maps_drm_buffer)
101
using namespace testing;
102
void *map_addr{reinterpret_cast<void*>(0xabcdef)};
104
EXPECT_CALL(*drm_fd_handler, primeFDToHandle(_,_))
105
.WillOnce(Return(0));
106
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_MODE_MAP_DUMB,_))
107
.WillOnce(Return(0));
108
EXPECT_CALL(*drm_fd_handler, map(_,_))
109
.WillOnce(Return(map_addr));
110
EXPECT_CALL(*drm_fd_handler, unmap(_,_))
112
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_GEM_CLOSE,_))
115
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
117
auto mem_region = buffer.secure_for_cpu_write();
118
ASSERT_EQ(map_addr, mem_region->vaddr.get());
119
ASSERT_EQ(width, mem_region->width);
120
ASSERT_EQ(height, mem_region->height);
121
ASSERT_EQ(stride, mem_region->stride);
122
ASSERT_EQ(pf, mem_region->format);
125
TEST_F(MirGBMBufferTest, secure_for_cpu_write_throws_on_prime_handle_failure)
127
using namespace testing;
129
EXPECT_CALL(*drm_fd_handler, primeFDToHandle(_,_))
130
.WillOnce(Return(-1));
131
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_MODE_MAP_DUMB,_))
133
EXPECT_CALL(*drm_fd_handler, map(_,_))
135
EXPECT_CALL(*drm_fd_handler, unmap(_,_))
137
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_GEM_CLOSE,_))
140
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
143
buffer.secure_for_cpu_write();
144
}, std::runtime_error);
147
TEST_F(MirGBMBufferTest, secure_for_cpu_write_throws_on_map_dumb_failure)
149
using namespace testing;
151
EXPECT_CALL(*drm_fd_handler, primeFDToHandle(_,_))
152
.WillOnce(Return(0));
153
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_MODE_MAP_DUMB,_))
154
.WillOnce(Return(1));
155
EXPECT_CALL(*drm_fd_handler, map(_,_))
157
EXPECT_CALL(*drm_fd_handler, unmap(_,_))
159
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_GEM_CLOSE,_))
162
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
165
auto mem_region = buffer.secure_for_cpu_write();
166
}, std::runtime_error);
169
TEST_F(MirGBMBufferTest, secure_for_cpu_write_throws_on_map_failure)
171
using namespace testing;
173
EXPECT_CALL(*drm_fd_handler, primeFDToHandle(_,_))
174
.WillOnce(Return(0));
175
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_MODE_MAP_DUMB,_))
176
.WillOnce(Return(0));
177
EXPECT_CALL(*drm_fd_handler, map(_,_))
178
.WillOnce(Return(MAP_FAILED));
179
EXPECT_CALL(*drm_fd_handler, unmap(_,_))
181
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_GEM_CLOSE,_))
184
mclg::GBMClientBuffer buffer(drm_fd_handler, std::move(package), size, pf);
187
auto mem_region = buffer.secure_for_cpu_write();
188
}, std::runtime_error);
191
TEST_F(MirGBMBufferTest, prime_fd_closed_on_buffer_destruction)
193
using namespace testing;
195
int const prime_fd{42};
197
package->fd[0] = prime_fd;
198
package->fd_items = 1;
200
EXPECT_CALL(*drm_fd_handler, close(prime_fd))
203
mclg::GBMClientBuffer buffer(drm_fd_handler, package, size, pf);
206
TEST_F(MirGBMBufferTest, buffer_does_not_take_a_gem_reference_when_not_mapping)
208
using namespace testing;
210
// We don't map the buffer, so we don't need to take a GEM reference...
211
EXPECT_CALL(*drm_fd_handler, primeFDToHandle(_,_))
213
// We haven't taken a GEM reference, so we shouldn't close it.
214
EXPECT_CALL(*drm_fd_handler, ioctl(DRM_IOCTL_GEM_CLOSE,_))
217
mclg::GBMClientBuffer buffer(drm_fd_handler, package, size, pf);
220
TEST_F(MirGBMBufferTest, factory_gets_size_from_package)
222
using namespace testing;
224
mclg::GBMClientBufferFactory factory(drm_fd_handler);
226
geom::Size unused_size{0, 0};
227
auto buffer = factory.create_buffer(package, unused_size, pf);
229
auto const& buf_size = buffer->size();
230
EXPECT_EQ(package->width, buf_size.width.as_int());
231
EXPECT_EQ(package->height, buf_size.height.as_int());
233
EXPECT_NE(unused_size, buf_size);