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 13 using ::testing::_; 14 using ::testing::Return; 15 using ::testing::StrictMock; 16 17 namespace gpu { 18 namespace gles2 { 19 20 class 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(); 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 82 class BufferManagerTest : public BufferManagerTestBase { 83 protected: 84 virtual void SetUp() { 85 SetUpBase(NULL, NULL, ""); 86 } 87 }; 88 89 class 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 99 class 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 116 TEST_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 154 TEST_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 176 TEST_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 193 TEST_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 215 TEST_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 240 TEST_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 276 TEST_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 315 TEST_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 355 TEST_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. 375 TEST_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 390 TEST_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