1 // Copyright (c) 2012 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.
5 #include "gpu/command_buffer/service/buffer_manager.h"
6 #include "gpu/command_buffer/service/error_state_mock.h"
7 #include "gpu/command_buffer/service/feature_info.h"
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/mocks.h"
10 #include "gpu/command_buffer/service/test_helper.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gl/gl_mock.h"
15 using ::testing::Return
;
16 using ::testing::StrictMock
;
21 class BufferManagerTestBase
: public GpuServiceTest
{
24 MemoryTracker
* memory_tracker
,
25 FeatureInfo
* feature_info
,
26 const char* extensions
) {
27 GpuServiceTest::SetUp();
29 TestHelper::SetupFeatureInfoInitExpectations(gl_
.get(), extensions
);
30 feature_info
->Initialize();
32 error_state_
.reset(new MockErrorState());
33 manager_
.reset(new BufferManager(memory_tracker
, feature_info
));
36 void TearDown() override
{
37 manager_
->Destroy(false);
40 GpuServiceTest::TearDown();
43 GLenum
GetTarget(const Buffer
* buffer
) const {
44 return buffer
->target();
48 Buffer
* buffer
, GLsizeiptr size
, GLenum usage
, const GLvoid
* data
,
50 TestHelper::DoBufferData(
51 gl_
.get(), error_state_
.get(), manager_
.get(),
52 buffer
, size
, usage
, data
, error
);
56 Buffer
* buffer
, GLintptr offset
, GLsizeiptr size
,
59 if (!buffer
->CheckRange(offset
, size
)) {
60 EXPECT_CALL(*error_state_
, SetGLError(_
, _
, GL_INVALID_VALUE
, _
, _
))
62 .RetiresOnSaturation();
64 } else if (!buffer
->IsClientSideArray()) {
65 EXPECT_CALL(*gl_
, BufferSubData(
66 buffer
->target(), offset
, size
, _
))
68 .RetiresOnSaturation();
70 manager_
->DoBufferSubData(
71 error_state_
.get(), buffer
, offset
, size
, data
);
75 scoped_ptr
<BufferManager
> manager_
;
76 scoped_ptr
<MockErrorState
> error_state_
;
79 class BufferManagerTest
: public BufferManagerTestBase
{
81 void SetUp() override
{ SetUpBase(NULL
, NULL
, ""); }
84 class BufferManagerMemoryTrackerTest
: public BufferManagerTestBase
{
86 void SetUp() override
{
87 mock_memory_tracker_
= new StrictMock
<MockMemoryTracker
>();
88 SetUpBase(mock_memory_tracker_
.get(), NULL
, "");
91 scoped_refptr
<MockMemoryTracker
> mock_memory_tracker_
;
94 class BufferManagerClientSideArraysTest
: public BufferManagerTestBase
{
96 void SetUp() override
{
97 feature_info_
= new FeatureInfo();
98 feature_info_
->workarounds_
.use_client_side_arrays_for_stream_buffers
=
100 SetUpBase(NULL
, feature_info_
.get(), "");
103 scoped_refptr
<FeatureInfo
> feature_info_
;
106 #define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size, pool) \
107 EXPECT_CALL(*mock_memory_tracker_.get(), \
108 TrackMemoryAllocatedChange(old_size, new_size, pool)) \
109 .Times(1).RetiresOnSaturation()
111 TEST_F(BufferManagerTest
, Basic
) {
112 const GLuint kClientBuffer1Id
= 1;
113 const GLuint kServiceBuffer1Id
= 11;
114 const GLsizeiptr kBuffer1Size
= 123;
115 const GLuint kClientBuffer2Id
= 2;
116 // Check we can create buffer.
117 manager_
->CreateBuffer(kClientBuffer1Id
, kServiceBuffer1Id
);
118 // Check buffer got created.
119 Buffer
* buffer1
= manager_
->GetBuffer(kClientBuffer1Id
);
120 ASSERT_TRUE(buffer1
!= NULL
);
121 EXPECT_EQ(0u, GetTarget(buffer1
));
122 EXPECT_EQ(0, buffer1
->size());
123 EXPECT_EQ(static_cast<GLenum
>(GL_STATIC_DRAW
), buffer1
->usage());
124 EXPECT_FALSE(buffer1
->IsDeleted());
125 EXPECT_FALSE(buffer1
->IsClientSideArray());
126 EXPECT_EQ(kServiceBuffer1Id
, buffer1
->service_id());
127 GLuint client_id
= 0;
128 EXPECT_TRUE(manager_
->GetClientId(buffer1
->service_id(), &client_id
));
129 EXPECT_EQ(kClientBuffer1Id
, client_id
);
130 manager_
->SetTarget(buffer1
, GL_ELEMENT_ARRAY_BUFFER
);
131 EXPECT_EQ(static_cast<GLenum
>(GL_ELEMENT_ARRAY_BUFFER
), GetTarget(buffer1
));
132 // Check we and set its size.
133 DoBufferData(buffer1
, kBuffer1Size
, GL_DYNAMIC_DRAW
, NULL
, GL_NO_ERROR
);
134 EXPECT_EQ(kBuffer1Size
, buffer1
->size());
135 EXPECT_EQ(static_cast<GLenum
>(GL_DYNAMIC_DRAW
), buffer1
->usage());
136 // Check we get nothing for a non-existent buffer.
137 EXPECT_TRUE(manager_
->GetBuffer(kClientBuffer2Id
) == NULL
);
138 // Check trying to a remove non-existent buffers does not crash.
139 manager_
->RemoveBuffer(kClientBuffer2Id
);
140 // Check that it gets deleted when the last reference is released.
141 EXPECT_CALL(*gl_
, DeleteBuffersARB(1, ::testing::Pointee(kServiceBuffer1Id
)))
143 .RetiresOnSaturation();
144 // Check we can't get the buffer after we remove it.
145 manager_
->RemoveBuffer(kClientBuffer1Id
);
146 EXPECT_TRUE(manager_
->GetBuffer(kClientBuffer1Id
) == NULL
);
149 TEST_F(BufferManagerMemoryTrackerTest
, Basic
) {
150 const GLuint kClientBuffer1Id
= 1;
151 const GLuint kServiceBuffer1Id
= 11;
152 const GLsizeiptr kBuffer1Size1
= 123;
153 const GLsizeiptr kBuffer1Size2
= 456;
154 // Check we can create buffer.
155 EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kManaged
);
156 manager_
->CreateBuffer(kClientBuffer1Id
, kServiceBuffer1Id
);
157 // Check buffer got created.
158 Buffer
* buffer1
= manager_
->GetBuffer(kClientBuffer1Id
);
159 ASSERT_TRUE(buffer1
!= NULL
);
160 manager_
->SetTarget(buffer1
, GL_ELEMENT_ARRAY_BUFFER
);
161 // Check we and set its size.
162 EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size1
, MemoryTracker::kManaged
);
163 DoBufferData(buffer1
, kBuffer1Size1
, GL_DYNAMIC_DRAW
, NULL
, GL_NO_ERROR
);
164 EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size1
, 0, MemoryTracker::kManaged
);
165 EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size2
, MemoryTracker::kManaged
);
166 DoBufferData(buffer1
, kBuffer1Size2
, GL_DYNAMIC_DRAW
, NULL
, GL_NO_ERROR
);
167 // On delete it will get freed.
168 EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size2
, 0, MemoryTracker::kManaged
);
171 TEST_F(BufferManagerTest
, Destroy
) {
172 const GLuint kClient1Id
= 1;
173 const GLuint kService1Id
= 11;
174 // Check we can create buffer.
175 manager_
->CreateBuffer(kClient1Id
, kService1Id
);
176 // Check buffer got created.
177 Buffer
* buffer1
= manager_
->GetBuffer(kClient1Id
);
178 ASSERT_TRUE(buffer1
!= NULL
);
179 EXPECT_CALL(*gl_
, DeleteBuffersARB(1, ::testing::Pointee(kService1Id
)))
181 .RetiresOnSaturation();
182 manager_
->Destroy(true);
183 // Check the resources were released.
184 buffer1
= manager_
->GetBuffer(kClient1Id
);
185 ASSERT_TRUE(buffer1
== NULL
);
188 TEST_F(BufferManagerTest
, DoBufferSubData
) {
189 const GLuint kClientBufferId
= 1;
190 const GLuint kServiceBufferId
= 11;
191 const uint8 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
192 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
193 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
194 ASSERT_TRUE(buffer
!= NULL
);
195 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
196 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
197 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
198 EXPECT_TRUE(DoBufferSubData(buffer
, sizeof(data
), 0, data
));
199 EXPECT_FALSE(DoBufferSubData(buffer
, sizeof(data
), 1, data
));
200 EXPECT_FALSE(DoBufferSubData(buffer
, 0, sizeof(data
) + 1, data
));
201 EXPECT_FALSE(DoBufferSubData(buffer
, -1, sizeof(data
), data
));
202 EXPECT_FALSE(DoBufferSubData(buffer
, 0, -1, data
));
203 DoBufferData(buffer
, 1, GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
204 const int size
= 0x20000;
205 scoped_ptr
<uint8
[]> temp(new uint8
[size
]);
206 EXPECT_FALSE(DoBufferSubData(buffer
, 0 - size
, size
, temp
.get()));
207 EXPECT_FALSE(DoBufferSubData(buffer
, 1, size
/ 2, temp
.get()));
210 TEST_F(BufferManagerTest
, GetRange
) {
211 const GLuint kClientBufferId
= 1;
212 const GLuint kServiceBufferId
= 11;
213 const GLsizeiptr kDataSize
= 10;
214 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
215 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
216 ASSERT_TRUE(buffer
!= NULL
);
217 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
218 DoBufferData(buffer
, kDataSize
, GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
220 static_cast<const char*>(buffer
->GetRange(0, kDataSize
));
221 ASSERT_TRUE(buf
!= NULL
);
223 static_cast<const char*>(buffer
->GetRange(1, kDataSize
- 1));
224 EXPECT_EQ(buf
+ 1, buf1
);
225 EXPECT_TRUE(buffer
->GetRange(kDataSize
, 1) == NULL
);
226 EXPECT_TRUE(buffer
->GetRange(0, kDataSize
+ 1) == NULL
);
227 EXPECT_TRUE(buffer
->GetRange(-1, kDataSize
) == NULL
);
228 EXPECT_TRUE(buffer
->GetRange(-0, -1) == NULL
);
229 const int size
= 0x20000;
230 DoBufferData(buffer
, size
/ 2, GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
231 EXPECT_TRUE(buffer
->GetRange(0 - size
, size
) == NULL
);
232 EXPECT_TRUE(buffer
->GetRange(1, size
/ 2) == NULL
);
235 TEST_F(BufferManagerTest
, GetMaxValueForRangeUint8
) {
236 const GLuint kClientBufferId
= 1;
237 const GLuint kServiceBufferId
= 11;
238 const uint8 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
239 const uint8 new_data
[] = {100, 120, 110};
240 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
241 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
242 ASSERT_TRUE(buffer
!= NULL
);
243 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
244 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
245 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
247 // Check entire range succeeds.
248 EXPECT_TRUE(buffer
->GetMaxValueForRange(
249 0, 10, GL_UNSIGNED_BYTE
, &max_value
));
250 EXPECT_EQ(10u, max_value
);
251 // Check sub range succeeds.
252 EXPECT_TRUE(buffer
->GetMaxValueForRange(
253 4, 3, GL_UNSIGNED_BYTE
, &max_value
));
254 EXPECT_EQ(6u, max_value
);
255 // Check changing sub range succeeds.
256 EXPECT_TRUE(DoBufferSubData(buffer
, 4, sizeof(new_data
), new_data
));
257 EXPECT_TRUE(buffer
->GetMaxValueForRange(
258 4, 3, GL_UNSIGNED_BYTE
, &max_value
));
259 EXPECT_EQ(120u, max_value
);
261 EXPECT_TRUE(buffer
->GetMaxValueForRange(
262 0, 10, GL_UNSIGNED_BYTE
, &max_value
));
263 EXPECT_EQ(120u, max_value
);
264 // Check out of range fails.
265 EXPECT_FALSE(buffer
->GetMaxValueForRange(
266 0, 11, GL_UNSIGNED_BYTE
, &max_value
));
267 EXPECT_FALSE(buffer
->GetMaxValueForRange(
268 10, 1, GL_UNSIGNED_BYTE
, &max_value
));
271 TEST_F(BufferManagerTest
, GetMaxValueForRangeUint16
) {
272 const GLuint kClientBufferId
= 1;
273 const GLuint kServiceBufferId
= 11;
274 const uint16 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
275 const uint16 new_data
[] = {100, 120, 110};
276 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
277 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
278 ASSERT_TRUE(buffer
!= NULL
);
279 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
280 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
281 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
283 // Check entire range succeeds.
284 EXPECT_TRUE(buffer
->GetMaxValueForRange(
285 0, 10, GL_UNSIGNED_SHORT
, &max_value
));
286 EXPECT_EQ(10u, max_value
);
287 // Check odd offset fails for GL_UNSIGNED_SHORT.
288 EXPECT_FALSE(buffer
->GetMaxValueForRange(
289 1, 10, GL_UNSIGNED_SHORT
, &max_value
));
290 // Check sub range succeeds.
291 EXPECT_TRUE(buffer
->GetMaxValueForRange(
292 8, 3, GL_UNSIGNED_SHORT
, &max_value
));
293 EXPECT_EQ(6u, max_value
);
294 // Check changing sub range succeeds.
295 EXPECT_TRUE(DoBufferSubData(buffer
, 8, sizeof(new_data
), new_data
));
296 EXPECT_TRUE(buffer
->GetMaxValueForRange(
297 8, 3, GL_UNSIGNED_SHORT
, &max_value
));
298 EXPECT_EQ(120u, max_value
);
300 EXPECT_TRUE(buffer
->GetMaxValueForRange(
301 0, 10, GL_UNSIGNED_SHORT
, &max_value
));
302 EXPECT_EQ(120u, max_value
);
303 // Check out of range fails.
304 EXPECT_FALSE(buffer
->GetMaxValueForRange(
305 0, 11, GL_UNSIGNED_SHORT
, &max_value
));
306 EXPECT_FALSE(buffer
->GetMaxValueForRange(
307 20, 1, GL_UNSIGNED_SHORT
, &max_value
));
310 TEST_F(BufferManagerTest
, GetMaxValueForRangeUint32
) {
311 const GLuint kClientBufferId
= 1;
312 const GLuint kServiceBufferId
= 11;
313 const uint32 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
314 const uint32 new_data
[] = {100, 120, 110};
315 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
316 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
317 ASSERT_TRUE(buffer
!= NULL
);
318 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
319 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
320 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
322 // Check entire range succeeds.
324 buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
325 EXPECT_EQ(10u, max_value
);
326 // Check non aligned offsets fails for GL_UNSIGNED_INT.
328 buffer
->GetMaxValueForRange(1, 10, GL_UNSIGNED_INT
, &max_value
));
330 buffer
->GetMaxValueForRange(2, 10, GL_UNSIGNED_INT
, &max_value
));
332 buffer
->GetMaxValueForRange(3, 10, GL_UNSIGNED_INT
, &max_value
));
333 // Check sub range succeeds.
334 EXPECT_TRUE(buffer
->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT
, &max_value
));
335 EXPECT_EQ(6u, max_value
);
336 // Check changing sub range succeeds.
337 EXPECT_TRUE(DoBufferSubData(buffer
, 16, sizeof(new_data
), new_data
));
338 EXPECT_TRUE(buffer
->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT
, &max_value
));
339 EXPECT_EQ(120u, max_value
);
341 EXPECT_TRUE(buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
342 EXPECT_EQ(120u, max_value
);
343 // Check out of range fails.
345 buffer
->GetMaxValueForRange(0, 11, GL_UNSIGNED_INT
, &max_value
));
347 buffer
->GetMaxValueForRange(40, 1, GL_UNSIGNED_INT
, &max_value
));
350 TEST_F(BufferManagerTest
, UseDeletedBuffer
) {
351 const GLuint kClientBufferId
= 1;
352 const GLuint kServiceBufferId
= 11;
353 const GLsizeiptr kDataSize
= 10;
354 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
355 scoped_refptr
<Buffer
> buffer
= manager_
->GetBuffer(kClientBufferId
);
356 ASSERT_TRUE(buffer
.get() != NULL
);
357 manager_
->SetTarget(buffer
.get(), GL_ARRAY_BUFFER
);
359 manager_
->RemoveBuffer(kClientBufferId
);
360 // Use it after removing
361 DoBufferData(buffer
.get(), kDataSize
, GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
362 // Check that it gets deleted when the last reference is released.
363 EXPECT_CALL(*gl_
, DeleteBuffersARB(1, ::testing::Pointee(kServiceBufferId
)))
365 .RetiresOnSaturation();
369 // Test buffers get shadowed when they are supposed to be.
370 TEST_F(BufferManagerClientSideArraysTest
, StreamBuffersAreShadowed
) {
371 const GLuint kClientBufferId
= 1;
372 const GLuint kServiceBufferId
= 11;
373 static const uint32 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
374 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
375 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
376 ASSERT_TRUE(buffer
!= NULL
);
377 manager_
->SetTarget(buffer
, GL_ARRAY_BUFFER
);
378 DoBufferData(buffer
, sizeof(data
), GL_STREAM_DRAW
, data
, GL_NO_ERROR
);
379 EXPECT_TRUE(buffer
->IsClientSideArray());
380 EXPECT_EQ(0, memcmp(data
, buffer
->GetRange(0, sizeof(data
)), sizeof(data
)));
381 DoBufferData(buffer
, sizeof(data
), GL_DYNAMIC_DRAW
, data
, GL_NO_ERROR
);
382 EXPECT_FALSE(buffer
->IsClientSideArray());
385 TEST_F(BufferManagerTest
, MaxValueCacheClearedCorrectly
) {
386 const GLuint kClientBufferId
= 1;
387 const GLuint kServiceBufferId
= 11;
388 const uint32 data1
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
389 const uint32 data2
[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
390 const uint32 data3
[] = {30, 29, 28};
391 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
392 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
393 ASSERT_TRUE(buffer
!= NULL
);
394 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
396 // Load the buffer with some initial data, and then get the maximum value for
397 // a range, which has the side effect of caching it.
398 DoBufferData(buffer
, sizeof(data1
), GL_STATIC_DRAW
, data1
, GL_NO_ERROR
);
400 buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
401 EXPECT_EQ(10u, max_value
);
402 // Check that any cached values are invalidated if the buffer is reloaded
403 // with the same amount of data (but different content)
404 ASSERT_EQ(sizeof(data2
), sizeof(data1
));
405 DoBufferData(buffer
, sizeof(data2
), GL_STATIC_DRAW
, data2
, GL_NO_ERROR
);
407 buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
408 EXPECT_EQ(20u, max_value
);
409 // Check that any cached values are invalidated if the buffer is reloaded
410 // with entirely different content.
411 ASSERT_NE(sizeof(data3
), sizeof(data1
));
412 DoBufferData(buffer
, sizeof(data3
), GL_STATIC_DRAW
, data3
, GL_NO_ERROR
);
414 buffer
->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT
, &max_value
));
415 EXPECT_EQ(30u, max_value
);