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 virtual void TearDown() {
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 virtual void SetUp() {
82 SetUpBase(NULL
, NULL
, "");
86 class BufferManagerMemoryTrackerTest
: public BufferManagerTestBase
{
88 virtual void SetUp() {
89 mock_memory_tracker_
= new StrictMock
<MockMemoryTracker
>();
90 SetUpBase(mock_memory_tracker_
.get(), NULL
, "");
93 scoped_refptr
<MockMemoryTracker
> mock_memory_tracker_
;
96 class BufferManagerClientSideArraysTest
: public BufferManagerTestBase
{
98 virtual void SetUp() {
99 feature_info_
= new FeatureInfo();
100 feature_info_
->workarounds_
.use_client_side_arrays_for_stream_buffers
=
102 SetUpBase(NULL
, feature_info_
.get(), "");
105 scoped_refptr
<FeatureInfo
> feature_info_
;
108 #define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size, pool) \
109 EXPECT_CALL(*mock_memory_tracker_.get(), \
110 TrackMemoryAllocatedChange(old_size, new_size, pool)) \
111 .Times(1).RetiresOnSaturation()
113 TEST_F(BufferManagerTest
, Basic
) {
114 const GLuint kClientBuffer1Id
= 1;
115 const GLuint kServiceBuffer1Id
= 11;
116 const GLsizeiptr kBuffer1Size
= 123;
117 const GLuint kClientBuffer2Id
= 2;
118 // Check we can create buffer.
119 manager_
->CreateBuffer(kClientBuffer1Id
, kServiceBuffer1Id
);
120 // Check buffer got created.
121 Buffer
* buffer1
= manager_
->GetBuffer(kClientBuffer1Id
);
122 ASSERT_TRUE(buffer1
!= NULL
);
123 EXPECT_EQ(0u, GetTarget(buffer1
));
124 EXPECT_EQ(0, buffer1
->size());
125 EXPECT_EQ(static_cast<GLenum
>(GL_STATIC_DRAW
), buffer1
->usage());
126 EXPECT_FALSE(buffer1
->IsDeleted());
127 EXPECT_FALSE(buffer1
->IsClientSideArray());
128 EXPECT_EQ(kServiceBuffer1Id
, buffer1
->service_id());
129 GLuint client_id
= 0;
130 EXPECT_TRUE(manager_
->GetClientId(buffer1
->service_id(), &client_id
));
131 EXPECT_EQ(kClientBuffer1Id
, client_id
);
132 manager_
->SetTarget(buffer1
, GL_ELEMENT_ARRAY_BUFFER
);
133 EXPECT_EQ(static_cast<GLenum
>(GL_ELEMENT_ARRAY_BUFFER
), GetTarget(buffer1
));
134 // Check we and set its size.
135 DoBufferData(buffer1
, kBuffer1Size
, GL_DYNAMIC_DRAW
, NULL
, GL_NO_ERROR
);
136 EXPECT_EQ(kBuffer1Size
, buffer1
->size());
137 EXPECT_EQ(static_cast<GLenum
>(GL_DYNAMIC_DRAW
), buffer1
->usage());
138 // Check we get nothing for a non-existent buffer.
139 EXPECT_TRUE(manager_
->GetBuffer(kClientBuffer2Id
) == NULL
);
140 // Check trying to a remove non-existent buffers does not crash.
141 manager_
->RemoveBuffer(kClientBuffer2Id
);
142 // Check that it gets deleted when the last reference is released.
143 EXPECT_CALL(*gl_
, DeleteBuffersARB(1, ::testing::Pointee(kServiceBuffer1Id
)))
145 .RetiresOnSaturation();
146 // Check we can't get the buffer after we remove it.
147 manager_
->RemoveBuffer(kClientBuffer1Id
);
148 EXPECT_TRUE(manager_
->GetBuffer(kClientBuffer1Id
) == NULL
);
151 TEST_F(BufferManagerMemoryTrackerTest
, Basic
) {
152 const GLuint kClientBuffer1Id
= 1;
153 const GLuint kServiceBuffer1Id
= 11;
154 const GLsizeiptr kBuffer1Size1
= 123;
155 const GLsizeiptr kBuffer1Size2
= 456;
156 // Check we can create buffer.
157 EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kManaged
);
158 manager_
->CreateBuffer(kClientBuffer1Id
, kServiceBuffer1Id
);
159 // Check buffer got created.
160 Buffer
* buffer1
= manager_
->GetBuffer(kClientBuffer1Id
);
161 ASSERT_TRUE(buffer1
!= NULL
);
162 manager_
->SetTarget(buffer1
, GL_ELEMENT_ARRAY_BUFFER
);
163 // Check we and set its size.
164 EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size1
, MemoryTracker::kManaged
);
165 DoBufferData(buffer1
, kBuffer1Size1
, GL_DYNAMIC_DRAW
, NULL
, GL_NO_ERROR
);
166 EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size1
, 0, MemoryTracker::kManaged
);
167 EXPECT_MEMORY_ALLOCATION_CHANGE(0, kBuffer1Size2
, MemoryTracker::kManaged
);
168 DoBufferData(buffer1
, kBuffer1Size2
, GL_DYNAMIC_DRAW
, NULL
, GL_NO_ERROR
);
169 // On delete it will get freed.
170 EXPECT_MEMORY_ALLOCATION_CHANGE(kBuffer1Size2
, 0, MemoryTracker::kManaged
);
173 TEST_F(BufferManagerTest
, Destroy
) {
174 const GLuint kClient1Id
= 1;
175 const GLuint kService1Id
= 11;
176 // Check we can create buffer.
177 manager_
->CreateBuffer(kClient1Id
, kService1Id
);
178 // Check buffer got created.
179 Buffer
* buffer1
= manager_
->GetBuffer(kClient1Id
);
180 ASSERT_TRUE(buffer1
!= NULL
);
181 EXPECT_CALL(*gl_
, DeleteBuffersARB(1, ::testing::Pointee(kService1Id
)))
183 .RetiresOnSaturation();
184 manager_
->Destroy(true);
185 // Check the resources were released.
186 buffer1
= manager_
->GetBuffer(kClient1Id
);
187 ASSERT_TRUE(buffer1
== NULL
);
190 TEST_F(BufferManagerTest
, DoBufferSubData
) {
191 const GLuint kClientBufferId
= 1;
192 const GLuint kServiceBufferId
= 11;
193 const uint8 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
194 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
195 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
196 ASSERT_TRUE(buffer
!= NULL
);
197 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
198 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
199 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
200 EXPECT_TRUE(DoBufferSubData(buffer
, sizeof(data
), 0, data
));
201 EXPECT_FALSE(DoBufferSubData(buffer
, sizeof(data
), 1, data
));
202 EXPECT_FALSE(DoBufferSubData(buffer
, 0, sizeof(data
) + 1, data
));
203 EXPECT_FALSE(DoBufferSubData(buffer
, -1, sizeof(data
), data
));
204 EXPECT_FALSE(DoBufferSubData(buffer
, 0, -1, data
));
205 DoBufferData(buffer
, 1, GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
206 const int size
= 0x20000;
207 scoped_ptr
<uint8
[]> temp(new uint8
[size
]);
208 EXPECT_FALSE(DoBufferSubData(buffer
, 0 - size
, size
, temp
.get()));
209 EXPECT_FALSE(DoBufferSubData(buffer
, 1, size
/ 2, temp
.get()));
212 TEST_F(BufferManagerTest
, GetRange
) {
213 const GLuint kClientBufferId
= 1;
214 const GLuint kServiceBufferId
= 11;
215 const uint8 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
216 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
217 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
218 ASSERT_TRUE(buffer
!= NULL
);
219 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
220 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
222 static_cast<const char*>(buffer
->GetRange(0, sizeof(data
)));
223 ASSERT_TRUE(buf
!= NULL
);
225 static_cast<const char*>(buffer
->GetRange(1, sizeof(data
) - 1));
226 EXPECT_EQ(buf
+ 1, buf1
);
227 EXPECT_TRUE(buffer
->GetRange(sizeof(data
), 1) == NULL
);
228 EXPECT_TRUE(buffer
->GetRange(0, sizeof(data
) + 1) == NULL
);
229 EXPECT_TRUE(buffer
->GetRange(-1, sizeof(data
)) == NULL
);
230 EXPECT_TRUE(buffer
->GetRange(-0, -1) == NULL
);
231 const int size
= 0x20000;
232 DoBufferData(buffer
, size
/ 2, GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
233 EXPECT_TRUE(buffer
->GetRange(0 - size
, size
) == NULL
);
234 EXPECT_TRUE(buffer
->GetRange(1, size
/ 2) == NULL
);
237 TEST_F(BufferManagerTest
, GetMaxValueForRangeUint8
) {
238 const GLuint kClientBufferId
= 1;
239 const GLuint kServiceBufferId
= 11;
240 const uint8 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
241 const uint8 new_data
[] = {100, 120, 110};
242 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
243 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
244 ASSERT_TRUE(buffer
!= NULL
);
245 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
246 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
247 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
249 // Check entire range succeeds.
250 EXPECT_TRUE(buffer
->GetMaxValueForRange(
251 0, 10, GL_UNSIGNED_BYTE
, &max_value
));
252 EXPECT_EQ(10u, max_value
);
253 // Check sub range succeeds.
254 EXPECT_TRUE(buffer
->GetMaxValueForRange(
255 4, 3, GL_UNSIGNED_BYTE
, &max_value
));
256 EXPECT_EQ(6u, max_value
);
257 // Check changing sub range succeeds.
258 EXPECT_TRUE(DoBufferSubData(buffer
, 4, sizeof(new_data
), new_data
));
259 EXPECT_TRUE(buffer
->GetMaxValueForRange(
260 4, 3, GL_UNSIGNED_BYTE
, &max_value
));
261 EXPECT_EQ(120u, max_value
);
263 EXPECT_TRUE(buffer
->GetMaxValueForRange(
264 0, 10, GL_UNSIGNED_BYTE
, &max_value
));
265 EXPECT_EQ(120u, max_value
);
266 // Check out of range fails.
267 EXPECT_FALSE(buffer
->GetMaxValueForRange(
268 0, 11, GL_UNSIGNED_BYTE
, &max_value
));
269 EXPECT_FALSE(buffer
->GetMaxValueForRange(
270 10, 1, GL_UNSIGNED_BYTE
, &max_value
));
273 TEST_F(BufferManagerTest
, GetMaxValueForRangeUint16
) {
274 const GLuint kClientBufferId
= 1;
275 const GLuint kServiceBufferId
= 11;
276 const uint16 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
277 const uint16 new_data
[] = {100, 120, 110};
278 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
279 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
280 ASSERT_TRUE(buffer
!= NULL
);
281 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
282 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
283 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
285 // Check entire range succeeds.
286 EXPECT_TRUE(buffer
->GetMaxValueForRange(
287 0, 10, GL_UNSIGNED_SHORT
, &max_value
));
288 EXPECT_EQ(10u, max_value
);
289 // Check odd offset fails for GL_UNSIGNED_SHORT.
290 EXPECT_FALSE(buffer
->GetMaxValueForRange(
291 1, 10, GL_UNSIGNED_SHORT
, &max_value
));
292 // Check sub range succeeds.
293 EXPECT_TRUE(buffer
->GetMaxValueForRange(
294 8, 3, GL_UNSIGNED_SHORT
, &max_value
));
295 EXPECT_EQ(6u, max_value
);
296 // Check changing sub range succeeds.
297 EXPECT_TRUE(DoBufferSubData(buffer
, 8, sizeof(new_data
), new_data
));
298 EXPECT_TRUE(buffer
->GetMaxValueForRange(
299 8, 3, GL_UNSIGNED_SHORT
, &max_value
));
300 EXPECT_EQ(120u, max_value
);
302 EXPECT_TRUE(buffer
->GetMaxValueForRange(
303 0, 10, GL_UNSIGNED_SHORT
, &max_value
));
304 EXPECT_EQ(120u, max_value
);
305 // Check out of range fails.
306 EXPECT_FALSE(buffer
->GetMaxValueForRange(
307 0, 11, GL_UNSIGNED_SHORT
, &max_value
));
308 EXPECT_FALSE(buffer
->GetMaxValueForRange(
309 20, 1, GL_UNSIGNED_SHORT
, &max_value
));
312 TEST_F(BufferManagerTest
, GetMaxValueForRangeUint32
) {
313 const GLuint kClientBufferId
= 1;
314 const GLuint kServiceBufferId
= 11;
315 const uint32 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
316 const uint32 new_data
[] = {100, 120, 110};
317 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
318 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
319 ASSERT_TRUE(buffer
!= NULL
);
320 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
321 DoBufferData(buffer
, sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
322 EXPECT_TRUE(DoBufferSubData(buffer
, 0, sizeof(data
), data
));
324 // Check entire range succeeds.
326 buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
327 EXPECT_EQ(10u, max_value
);
328 // Check non aligned offsets fails for GL_UNSIGNED_INT.
330 buffer
->GetMaxValueForRange(1, 10, GL_UNSIGNED_INT
, &max_value
));
332 buffer
->GetMaxValueForRange(2, 10, GL_UNSIGNED_INT
, &max_value
));
334 buffer
->GetMaxValueForRange(3, 10, GL_UNSIGNED_INT
, &max_value
));
335 // Check sub range succeeds.
336 EXPECT_TRUE(buffer
->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT
, &max_value
));
337 EXPECT_EQ(6u, max_value
);
338 // Check changing sub range succeeds.
339 EXPECT_TRUE(DoBufferSubData(buffer
, 16, sizeof(new_data
), new_data
));
340 EXPECT_TRUE(buffer
->GetMaxValueForRange(16, 3, GL_UNSIGNED_INT
, &max_value
));
341 EXPECT_EQ(120u, max_value
);
343 EXPECT_TRUE(buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
344 EXPECT_EQ(120u, max_value
);
345 // Check out of range fails.
347 buffer
->GetMaxValueForRange(0, 11, GL_UNSIGNED_INT
, &max_value
));
349 buffer
->GetMaxValueForRange(40, 1, GL_UNSIGNED_INT
, &max_value
));
352 TEST_F(BufferManagerTest
, UseDeletedBuffer
) {
353 const GLuint kClientBufferId
= 1;
354 const GLuint kServiceBufferId
= 11;
355 const uint32 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
356 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
357 scoped_refptr
<Buffer
> buffer
= manager_
->GetBuffer(kClientBufferId
);
358 ASSERT_TRUE(buffer
.get() != NULL
);
359 manager_
->SetTarget(buffer
.get(), GL_ARRAY_BUFFER
);
361 manager_
->RemoveBuffer(kClientBufferId
);
362 // Use it after removing
363 DoBufferData(buffer
.get(), sizeof(data
), GL_STATIC_DRAW
, NULL
, GL_NO_ERROR
);
364 // Check that it gets deleted when the last reference is released.
365 EXPECT_CALL(*gl_
, DeleteBuffersARB(1, ::testing::Pointee(kServiceBufferId
)))
367 .RetiresOnSaturation();
371 // Test buffers get shadowed when they are supposed to be.
372 TEST_F(BufferManagerClientSideArraysTest
, StreamBuffersAreShadowed
) {
373 const GLuint kClientBufferId
= 1;
374 const GLuint kServiceBufferId
= 11;
375 static const uint32 data
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
376 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
377 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
378 ASSERT_TRUE(buffer
!= NULL
);
379 manager_
->SetTarget(buffer
, GL_ARRAY_BUFFER
);
380 DoBufferData(buffer
, sizeof(data
), GL_STREAM_DRAW
, data
, GL_NO_ERROR
);
381 EXPECT_TRUE(buffer
->IsClientSideArray());
382 EXPECT_EQ(0, memcmp(data
, buffer
->GetRange(0, sizeof(data
)), sizeof(data
)));
383 DoBufferData(buffer
, sizeof(data
), GL_DYNAMIC_DRAW
, data
, GL_NO_ERROR
);
384 EXPECT_FALSE(buffer
->IsClientSideArray());
387 TEST_F(BufferManagerTest
, MaxValueCacheClearedCorrectly
) {
388 const GLuint kClientBufferId
= 1;
389 const GLuint kServiceBufferId
= 11;
390 const uint32 data1
[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
391 const uint32 data2
[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
392 const uint32 data3
[] = {30, 29, 28};
393 manager_
->CreateBuffer(kClientBufferId
, kServiceBufferId
);
394 Buffer
* buffer
= manager_
->GetBuffer(kClientBufferId
);
395 ASSERT_TRUE(buffer
!= NULL
);
396 manager_
->SetTarget(buffer
, GL_ELEMENT_ARRAY_BUFFER
);
398 // Load the buffer with some initial data, and then get the maximum value for
399 // a range, which has the side effect of caching it.
400 DoBufferData(buffer
, sizeof(data1
), GL_STATIC_DRAW
, data1
, GL_NO_ERROR
);
402 buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
403 EXPECT_EQ(10u, max_value
);
404 // Check that any cached values are invalidated if the buffer is reloaded
405 // with the same amount of data (but different content)
406 ASSERT_EQ(sizeof(data2
), sizeof(data1
));
407 DoBufferData(buffer
, sizeof(data2
), GL_STATIC_DRAW
, data2
, GL_NO_ERROR
);
409 buffer
->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT
, &max_value
));
410 EXPECT_EQ(20u, max_value
);
411 // Check that any cached values are invalidated if the buffer is reloaded
412 // with entirely different content.
413 ASSERT_NE(sizeof(data3
), sizeof(data1
));
414 DoBufferData(buffer
, sizeof(data3
), GL_STATIC_DRAW
, data3
, GL_NO_ERROR
);
416 buffer
->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT
, &max_value
));
417 EXPECT_EQ(30u, max_value
);