OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/common/gpu/client/gpu_memory_buffer_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "content/common/gpu/gpu_memory_buffer_factory.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 #include "ui/gfx/buffer_format_util.h" | |
11 | |
12 namespace content { | |
13 namespace { | |
14 | |
15 const int kClientId = 1; | |
16 | |
17 class GpuMemoryBufferImplTest | |
18 : public testing::TestWithParam<gfx::GpuMemoryBufferType> { | |
19 public: | |
20 GpuMemoryBufferImplTest() : buffer_count_(0), factory_(nullptr) {} | |
21 | |
22 // Overridden from testing::Test: | |
23 void SetUp() override { | |
24 factory_ = GpuMemoryBufferFactory::Create(GetParam()); | |
25 factory_->GetSupportedGpuMemoryBufferConfigurations( | |
26 &supported_configurations_); | |
27 } | |
28 void TearDown() override { factory_.reset(); } | |
29 | |
30 gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id, | |
31 const gfx::Size& size, | |
32 gfx::BufferFormat format, | |
33 gfx::BufferUsage usage) { | |
34 ++buffer_count_; | |
35 return factory_->CreateGpuMemoryBuffer(id, size, format, usage, kClientId, | |
36 gfx::kNullPluginWindow); | |
37 } | |
38 | |
39 void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, uint32 sync_point) { | |
40 factory_->DestroyGpuMemoryBuffer(id, kClientId); | |
41 DCHECK_GT(buffer_count_, 0); | |
42 --buffer_count_; | |
43 } | |
44 | |
45 std::vector<GpuMemoryBufferFactory::Configuration> supported_configurations_; | |
46 int buffer_count_; | |
47 | |
48 private: | |
49 scoped_ptr<GpuMemoryBufferFactory> factory_; | |
50 }; | |
51 | |
52 TEST_P(GpuMemoryBufferImplTest, CreateFromHandle) { | |
53 const gfx::GpuMemoryBufferId kBufferId(1); | |
54 | |
55 gfx::Size buffer_size(8, 8); | |
56 | |
57 for (auto configuration : supported_configurations_) { | |
58 scoped_ptr<GpuMemoryBufferImpl> buffer( | |
59 GpuMemoryBufferImpl::CreateFromHandle( | |
60 CreateGpuMemoryBuffer(kBufferId, buffer_size, configuration.format, | |
61 configuration.usage), | |
62 buffer_size, configuration.format, configuration.usage, | |
63 base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer, | |
64 base::Unretained(this), kBufferId))); | |
65 EXPECT_EQ(1, buffer_count_); | |
66 ASSERT_TRUE(buffer); | |
67 EXPECT_EQ(buffer->GetFormat(), configuration.format); | |
68 | |
69 // Check if destruction callback is executed when deleting the buffer. | |
70 buffer.reset(); | |
71 EXPECT_EQ(0, buffer_count_); | |
72 } | |
73 } | |
74 | |
75 TEST_P(GpuMemoryBufferImplTest, Map) { | |
76 const gfx::GpuMemoryBufferId kBufferId(1); | |
77 | |
78 // Use a multiple of 4 for both dimensions to support compressed formats. | |
79 gfx::Size buffer_size(4, 4); | |
80 | |
81 for (auto configuration : supported_configurations_) { | |
82 if (configuration.usage != gfx::BufferUsage::MAP) | |
83 continue; | |
84 | |
85 scoped_ptr<GpuMemoryBufferImpl> buffer( | |
86 GpuMemoryBufferImpl::CreateFromHandle( | |
87 CreateGpuMemoryBuffer(kBufferId, buffer_size, configuration.format, | |
88 configuration.usage), | |
89 buffer_size, configuration.format, configuration.usage, | |
90 base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer, | |
91 base::Unretained(this), kBufferId))); | |
92 ASSERT_TRUE(buffer); | |
93 EXPECT_FALSE(buffer->IsMapped()); | |
94 | |
95 size_t num_planes = | |
96 gfx::NumberOfPlanesForBufferFormat(configuration.format); | |
97 | |
98 // Map buffer into user space. | |
99 scoped_ptr<void*[]> mapped_buffers(new void*[num_planes]); | |
100 bool rv = buffer->Map(mapped_buffers.get()); | |
101 ASSERT_TRUE(rv); | |
102 EXPECT_TRUE(buffer->IsMapped()); | |
103 | |
104 // Get strides. | |
105 scoped_ptr<int[]> strides(new int[num_planes]); | |
106 buffer->GetStride(strides.get()); | |
107 | |
108 // Copy and compare mapped buffers. | |
109 for (size_t plane = 0; plane < num_planes; ++plane) { | |
110 size_t row_size_in_bytes = 0; | |
111 EXPECT_TRUE(gfx::RowSizeForBufferFormatChecked( | |
112 buffer_size.width(), configuration.format, plane, | |
113 &row_size_in_bytes)); | |
114 EXPECT_GT(row_size_in_bytes, 0u); | |
115 | |
116 scoped_ptr<char[]> data(new char[row_size_in_bytes]); | |
117 memset(data.get(), 0x2a + plane, row_size_in_bytes); | |
118 | |
119 size_t height = | |
120 buffer_size.height() / | |
121 gfx::SubsamplingFactorForBufferFormat(configuration.format, plane); | |
122 for (size_t y = 0; y < height; ++y) { | |
123 memcpy(static_cast<char*>(mapped_buffers[plane]) + y * strides[plane], | |
124 data.get(), row_size_in_bytes); | |
125 EXPECT_EQ(memcmp(static_cast<char*>(mapped_buffers[plane]) + | |
126 y * strides[plane], | |
127 data.get(), row_size_in_bytes), | |
128 0); | |
129 } | |
130 } | |
131 | |
132 buffer->Unmap(); | |
133 EXPECT_FALSE(buffer->IsMapped()); | |
134 } | |
135 } | |
136 | |
137 TEST_P(GpuMemoryBufferImplTest, PersistentMap) { | |
138 const gfx::GpuMemoryBufferId kBufferId(1); | |
139 | |
140 // Use a multiple of 4 for both dimensions to support compressed formats. | |
141 gfx::Size buffer_size(4, 4); | |
142 | |
143 for (auto configuration : supported_configurations_) { | |
144 if (configuration.usage != gfx::BufferUsage::PERSISTENT_MAP) | |
145 continue; | |
146 | |
147 scoped_ptr<GpuMemoryBufferImpl> buffer( | |
148 GpuMemoryBufferImpl::CreateFromHandle( | |
149 CreateGpuMemoryBuffer(kBufferId, buffer_size, configuration.format, | |
150 configuration.usage), | |
151 buffer_size, configuration.format, configuration.usage, | |
152 base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer, | |
153 base::Unretained(this), kBufferId))); | |
154 ASSERT_TRUE(buffer); | |
155 EXPECT_FALSE(buffer->IsMapped()); | |
156 | |
157 size_t num_planes = | |
158 gfx::NumberOfPlanesForBufferFormat(configuration.format); | |
159 | |
160 // Map buffer into user space. | |
161 scoped_ptr<void* []> mapped_buffers(new void* [num_planes]); | |
162 bool rv = buffer->Map(mapped_buffers.get()); | |
163 ASSERT_TRUE(rv); | |
164 EXPECT_TRUE(buffer->IsMapped()); | |
165 | |
166 // Get strides. | |
167 scoped_ptr<int[]> strides(new int[num_planes]); | |
168 buffer->GetStride(strides.get()); | |
169 | |
170 // Copy and compare mapped buffers. | |
171 for (size_t plane = 0; plane < num_planes; ++plane) { | |
172 size_t row_size_in_bytes; | |
173 EXPECT_TRUE(gfx::RowSizeForBufferFormatChecked( | |
174 buffer_size.width(), configuration.format, plane, | |
175 &row_size_in_bytes)); | |
176 | |
177 scoped_ptr<char[]> data(new char[row_size_in_bytes]); | |
178 memset(data.get(), 0x2a + plane, row_size_in_bytes); | |
179 | |
180 size_t height = | |
181 buffer_size.height() / | |
182 gfx::SubsamplingFactorForBufferFormat(configuration.format, plane); | |
183 for (size_t y = 0; y < height; ++y) { | |
184 memcpy(static_cast<char*>(mapped_buffers[plane]) + y * strides[plane], | |
185 data.get(), row_size_in_bytes); | |
186 EXPECT_EQ(memcmp(static_cast<char*>(mapped_buffers[plane]) + | |
187 y * strides[plane], | |
188 data.get(), row_size_in_bytes), | |
189 0); | |
190 } | |
191 } | |
192 | |
193 buffer->Unmap(); | |
194 EXPECT_FALSE(buffer->IsMapped()); | |
195 | |
196 // Remap the buffer, and compare again. It should contain the same data. | |
197 rv = buffer->Map(mapped_buffers.get()); | |
198 ASSERT_TRUE(rv); | |
199 EXPECT_TRUE(buffer->IsMapped()); | |
200 | |
201 buffer->GetStride(strides.get()); | |
202 | |
203 for (size_t plane = 0; plane < num_planes; ++plane) { | |
204 size_t row_size_in_bytes; | |
205 EXPECT_TRUE(gfx::RowSizeForBufferFormatChecked( | |
206 buffer_size.width(), configuration.format, plane, | |
207 &row_size_in_bytes)); | |
208 | |
209 scoped_ptr<char[]> data(new char[row_size_in_bytes]); | |
210 memset(data.get(), 0x2a + plane, row_size_in_bytes); | |
211 | |
212 size_t height = | |
213 buffer_size.height() / | |
214 gfx::SubsamplingFactorForBufferFormat(configuration.format, plane); | |
215 for (size_t y = 0; y < height; ++y) { | |
216 EXPECT_EQ(memcmp(static_cast<char*>(mapped_buffers[plane]) + | |
217 y * strides[plane], | |
218 data.get(), row_size_in_bytes), | |
219 0); | |
220 } | |
221 } | |
222 | |
223 buffer->Unmap(); | |
224 EXPECT_FALSE(buffer->IsMapped()); | |
225 } | |
226 } | |
227 | |
228 std::vector<gfx::GpuMemoryBufferType> GetSupportedGpuMemoryBufferTypes() { | |
229 std::vector<gfx::GpuMemoryBufferType> supported_types; | |
230 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types); | |
231 return supported_types; | |
232 } | |
233 | |
234 INSTANTIATE_TEST_CASE_P( | |
235 GpuMemoryBufferImplTests, | |
236 GpuMemoryBufferImplTest, | |
237 ::testing::ValuesIn(GetSupportedGpuMemoryBufferTypes())); | |
238 | |
239 } // namespace | |
240 } // namespace content | |
OLD | NEW |