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.
4
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"
13
14using ::testing::_;
15using ::testing::Return;
16using ::testing::StrictMock;
17
18namespace gpu {
19namespace gles2 {
20
21class BufferManagerTestBase : public GpuServiceTest {
22 protected:
23  void SetUpBase(
24      MemoryTracker* memory_tracker,
25      FeatureInfo* feature_info,
26      const char* extensions) {
27    GpuServiceTest::SetUp();
28    if (feature_info) {
29      TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), extensions);
30      feature_info->Initialize();
31    }
32    error_state_.reset(new MockErrorState());
33    manager_.reset(new BufferManager(memory_tracker, feature_info));
34  }
35
36  virtual void TearDown() {
37    manager_->Destroy(false);
38    manager_.reset();
39    error_state_.reset();
40    GpuServiceTest::TearDown();
41  }
42
43  GLenum GetTarget(const Buffer* buffer) const {
44    return buffer->target();
45  }
46
47  void DoBufferData(
48      Buffer* buffer, GLsizeiptr size, GLenum usage, const GLvoid* data,
49      GLenum error) {
50    TestHelper::DoBufferData(
51        gl_.get(), error_state_.get(), manager_.get(),
52        buffer, size, usage, data, error);
53  }
54
55  bool DoBufferSubData(
56      Buffer* buffer, GLintptr offset, GLsizeiptr size,
57      const GLvoid* data) {
58    bool success = true;
59    if (!buffer->CheckRange(offset, size)) {
60      EXPECT_CALL(*error_state_, SetGLError(_, _, GL_INVALID_VALUE, _, _))
61         .Times(1)
62         .RetiresOnSaturation();
63      success = false;
64    } else if (!buffer->IsClientSideArray()) {
65      EXPECT_CALL(*gl_, BufferSubData(
66          buffer->target(), offset, size, _))
67          .Times(1)
68          .RetiresOnSaturation();
69    }
70    manager_->DoBufferSubData(
71        error_state_.get(), buffer, offset, size, data);
72    return success;
73  }
74
75  scoped_ptr<BufferManager> manager_;
76  scoped_ptr<MockErrorState> error_state_;
77};
78
79class BufferManagerTest : public BufferManagerTestBase {
80 protected:
81  virtual void SetUp() {
82    SetUpBase(NULL, NULL, "");
83  }
84};
85
86class BufferManagerMemoryTrackerTest : public BufferManagerTestBase {
87 protected:
88  virtual void SetUp() {
89    mock_memory_tracker_ = new StrictMock<MockMemoryTracker>();
90    SetUpBase(mock_memory_tracker_.get(), NULL, "");
91  }
92
93  scoped_refptr<MockMemoryTracker> mock_memory_tracker_;
94};
95
96class BufferManagerClientSideArraysTest : public BufferManagerTestBase {
97 protected:
98  virtual void SetUp() {
99    feature_info_ = new FeatureInfo();
100    feature_info_->workarounds_.use_client_side_arrays_for_stream_buffers =
101      true;
102    SetUpBase(NULL, feature_info_.get(), "");
103  }
104
105  scoped_refptr<FeatureInfo> feature_info_;
106};
107
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()
112
113TEST_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)))
144      .Times(1)
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);
149}
150
151TEST_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);
171}
172
173TEST_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)))
182      .Times(1)
183      .RetiresOnSaturation();
184  manager_->Destroy(true);
185  // Check the resources were released.
186  buffer1 = manager_->GetBuffer(kClient1Id);
187  ASSERT_TRUE(buffer1 == NULL);
188}
189
190TEST_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()));
210}
211
212TEST_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);
221  const char* buf =
222      static_cast<const char*>(buffer->GetRange(0, sizeof(data)));
223  ASSERT_TRUE(buf != NULL);
224  const char* buf1 =
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);
235}
236
237TEST_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));
248  GLuint max_value;
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);
262  max_value = 0;
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));
271}
272
273TEST_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));
284  GLuint max_value;
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);
301  max_value = 0;
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));
310}
311
312TEST_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));
323  GLuint max_value;
324  // Check entire range succeeds.
325  EXPECT_TRUE(
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.
329  EXPECT_FALSE(
330      buffer->GetMaxValueForRange(1, 10, GL_UNSIGNED_INT, &max_value));
331  EXPECT_FALSE(
332      buffer->GetMaxValueForRange(2, 10, GL_UNSIGNED_INT, &max_value));
333  EXPECT_FALSE(
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);
342  max_value = 0;
343  EXPECT_TRUE(buffer->GetMaxValueForRange(0, 10, GL_UNSIGNED_INT, &max_value));
344  EXPECT_EQ(120u, max_value);
345  // Check out of range fails.
346  EXPECT_FALSE(
347      buffer->GetMaxValueForRange(0, 11, GL_UNSIGNED_INT, &max_value));
348  EXPECT_FALSE(
349      buffer->GetMaxValueForRange(40, 1, GL_UNSIGNED_INT, &max_value));
350}
351
352TEST_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);
360  // Remove 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)))
366      .Times(1)
367      .RetiresOnSaturation();
368  buffer = NULL;
369}
370
371// Test buffers get shadowed when they are supposed to be.
372TEST_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());
385}
386
387TEST_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);
397  GLuint max_value;
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);
401  EXPECT_TRUE(
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);
408  EXPECT_TRUE(
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);
415  EXPECT_TRUE(
416      buffer->GetMaxValueForRange(0, 3, GL_UNSIGNED_INT, &max_value));
417  EXPECT_EQ(30u, max_value);
418}
419
420}  // namespace gles2
421}  // namespace gpu
422
423
424