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