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 // Tests for GLES2Implementation. 6 7 #include "gpu/command_buffer/client/gles2_implementation.h" 8 9 #include <GLES2/gl2ext.h> 10 #include <GLES2/gl2extchromium.h> 11 #include "gpu/command_buffer/client/client_test_helper.h" 12 #include "gpu/command_buffer/client/program_info_manager.h" 13 #include "gpu/command_buffer/client/transfer_buffer.h" 14 #include "gpu/command_buffer/common/command_buffer.h" 15 #include "gpu/command_buffer/common/compiler_specific.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 19 #if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 20 #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS 21 #endif 22 23 using testing::_; 24 using testing::AtLeast; 25 using testing::AnyNumber; 26 using testing::DoAll; 27 using testing::InSequence; 28 using testing::Invoke; 29 using testing::Mock; 30 using testing::Sequence; 31 using testing::StrictMock; 32 using testing::Truly; 33 using testing::Return; 34 35 namespace gpu { 36 namespace gles2 { 37 38 ACTION_P2(SetMemory, dst, obj) { 39 memcpy(dst, &obj, sizeof(obj)); 40 } 41 42 ACTION_P3(SetMemoryFromArray, dst, array, size) { 43 memcpy(dst, array, size); 44 } 45 46 // Used to help set the transfer buffer result to SizedResult of a single value. 47 template <typename T> 48 class SizedResultHelper { 49 public: 50 explicit SizedResultHelper(T result) 51 : size_(sizeof(result)), 52 result_(result) { 53 } 54 55 private: 56 uint32 size_; 57 T result_; 58 }; 59 60 // Struct to make it easy to pass a vec4 worth of floats. 61 struct FourFloats { 62 FourFloats(float _x, float _y, float _z, float _w) 63 : x(_x), 64 y(_y), 65 z(_z), 66 w(_w) { 67 } 68 69 float x; 70 float y; 71 float z; 72 float w; 73 }; 74 75 #pragma pack(push, 1) 76 // Struct that holds 7 characters. 77 struct Str7 { 78 char str[7]; 79 }; 80 #pragma pack(pop) 81 82 class MockTransferBuffer : public TransferBufferInterface { 83 public: 84 struct ExpectedMemoryInfo { 85 uint32 offset; 86 int32 id; 87 uint8* ptr; 88 }; 89 90 MockTransferBuffer( 91 CommandBuffer* command_buffer, 92 unsigned int size, 93 unsigned int result_size, 94 unsigned int alignment) 95 : command_buffer_(command_buffer), 96 size_(size), 97 result_size_(result_size), 98 alignment_(alignment), 99 actual_buffer_index_(0), 100 expected_buffer_index_(0), 101 last_alloc_(NULL), 102 expected_offset_(result_size), 103 actual_offset_(result_size) { 104 // We have to allocate the buffers here because 105 // we need to know their address before GLES2Implementation::Initialize 106 // is called. 107 for (int ii = 0; ii < kNumBuffers; ++ii) { 108 buffers_[ii] = command_buffer_->CreateTransferBuffer( 109 size_ + ii * alignment_, 110 &buffer_ids_[ii]); 111 EXPECT_NE(-1, buffer_ids_[ii]); 112 } 113 } 114 115 virtual ~MockTransferBuffer() { } 116 117 virtual bool Initialize( 118 unsigned int starting_buffer_size, 119 unsigned int result_size, 120 unsigned int /* min_buffer_size */, 121 unsigned int /* max_buffer_size */, 122 unsigned int alignment, 123 unsigned int size_to_flush) OVERRIDE; 124 virtual int GetShmId() OVERRIDE; 125 virtual void* GetResultBuffer() OVERRIDE; 126 virtual int GetResultOffset() OVERRIDE; 127 virtual void Free() OVERRIDE; 128 virtual bool HaveBuffer() const OVERRIDE; 129 virtual void* AllocUpTo( 130 unsigned int size, unsigned int* size_allocated) OVERRIDE; 131 virtual void* Alloc(unsigned int size) OVERRIDE; 132 virtual RingBuffer::Offset GetOffset(void* pointer) const OVERRIDE; 133 virtual void FreePendingToken(void* p, unsigned int /* token */) OVERRIDE; 134 135 size_t MaxTransferBufferSize() { 136 return size_ - result_size_; 137 } 138 139 unsigned int RoundToAlignment(unsigned int size) { 140 return (size + alignment_ - 1) & ~(alignment_ - 1); 141 } 142 143 bool InSync() { 144 return expected_buffer_index_ == actual_buffer_index_ && 145 expected_offset_ == actual_offset_; 146 } 147 148 ExpectedMemoryInfo GetExpectedMemory(size_t size) { 149 ExpectedMemoryInfo mem; 150 mem.offset = AllocateExpectedTransferBuffer(size); 151 mem.id = GetExpectedTransferBufferId(); 152 mem.ptr = static_cast<uint8*>( 153 GetExpectedTransferAddressFromOffset(mem.offset, size)); 154 return mem; 155 } 156 157 ExpectedMemoryInfo GetExpectedResultMemory(size_t size) { 158 ExpectedMemoryInfo mem; 159 mem.offset = GetExpectedResultBufferOffset(); 160 mem.id = GetExpectedResultBufferId(); 161 mem.ptr = static_cast<uint8*>( 162 GetExpectedTransferAddressFromOffset(mem.offset, size)); 163 return mem; 164 } 165 166 private: 167 static const int kNumBuffers = 2; 168 169 uint8* actual_buffer() const { 170 return static_cast<uint8*>(buffers_[actual_buffer_index_].ptr); 171 } 172 173 uint8* expected_buffer() const { 174 return static_cast<uint8*>(buffers_[expected_buffer_index_].ptr); 175 } 176 177 uint32 AllocateExpectedTransferBuffer(size_t size) { 178 EXPECT_LE(size, MaxTransferBufferSize()); 179 180 // Toggle which buffer we get each time to simulate the buffer being 181 // reallocated. 182 expected_buffer_index_ = (expected_buffer_index_ + 1) % kNumBuffers; 183 184 if (expected_offset_ + size > size_) { 185 expected_offset_ = result_size_; 186 } 187 uint32 offset = expected_offset_; 188 expected_offset_ += RoundToAlignment(size); 189 190 // Make sure each buffer has a different offset. 191 return offset + expected_buffer_index_ * alignment_; 192 } 193 194 void* GetExpectedTransferAddressFromOffset(uint32 offset, size_t size) { 195 EXPECT_GE(offset, expected_buffer_index_ * alignment_); 196 EXPECT_LE(offset + size, size_ + expected_buffer_index_ * alignment_); 197 return expected_buffer() + offset; 198 } 199 200 int GetExpectedResultBufferId() { 201 return buffer_ids_[expected_buffer_index_]; 202 } 203 204 uint32 GetExpectedResultBufferOffset() { 205 return expected_buffer_index_ * alignment_; 206 } 207 208 int GetExpectedTransferBufferId() { 209 return buffer_ids_[expected_buffer_index_]; 210 } 211 212 CommandBuffer* command_buffer_; 213 size_t size_; 214 size_t result_size_; 215 uint32 alignment_; 216 int buffer_ids_[kNumBuffers]; 217 gpu::Buffer buffers_[kNumBuffers]; 218 int actual_buffer_index_; 219 int expected_buffer_index_; 220 void* last_alloc_; 221 uint32 expected_offset_; 222 uint32 actual_offset_; 223 224 DISALLOW_COPY_AND_ASSIGN(MockTransferBuffer); 225 }; 226 227 bool MockTransferBuffer::Initialize( 228 unsigned int starting_buffer_size, 229 unsigned int result_size, 230 unsigned int /* min_buffer_size */, 231 unsigned int /* max_buffer_size */, 232 unsigned int alignment, 233 unsigned int /* size_to_flush */) { 234 // Just check they match. 235 return size_ == starting_buffer_size && 236 result_size_ == result_size && 237 alignment_ == alignment; 238 }; 239 240 int MockTransferBuffer::GetShmId() { 241 return buffer_ids_[actual_buffer_index_]; 242 } 243 244 void* MockTransferBuffer::GetResultBuffer() { 245 return actual_buffer() + actual_buffer_index_ * alignment_; 246 } 247 248 int MockTransferBuffer::GetResultOffset() { 249 return actual_buffer_index_ * alignment_; 250 } 251 252 void MockTransferBuffer::Free() { 253 GPU_NOTREACHED(); 254 } 255 256 bool MockTransferBuffer::HaveBuffer() const { 257 return true; 258 } 259 260 void* MockTransferBuffer::AllocUpTo( 261 unsigned int size, unsigned int* size_allocated) { 262 EXPECT_TRUE(size_allocated != NULL); 263 EXPECT_TRUE(last_alloc_ == NULL); 264 265 // Toggle which buffer we get each time to simulate the buffer being 266 // reallocated. 267 actual_buffer_index_ = (actual_buffer_index_ + 1) % kNumBuffers; 268 269 size = std::min(static_cast<size_t>(size), MaxTransferBufferSize()); 270 if (actual_offset_ + size > size_) { 271 actual_offset_ = result_size_; 272 } 273 uint32 offset = actual_offset_; 274 actual_offset_ += RoundToAlignment(size); 275 *size_allocated = size; 276 277 // Make sure each buffer has a different offset. 278 last_alloc_ = actual_buffer() + offset + actual_buffer_index_ * alignment_; 279 return last_alloc_; 280 } 281 282 void* MockTransferBuffer::Alloc(unsigned int size) { 283 EXPECT_LE(size, MaxTransferBufferSize()); 284 unsigned int temp = 0; 285 void* p = AllocUpTo(size, &temp); 286 EXPECT_EQ(temp, size); 287 return p; 288 } 289 290 RingBuffer::Offset MockTransferBuffer::GetOffset(void* pointer) const { 291 // Make sure each buffer has a different offset. 292 return static_cast<uint8*>(pointer) - actual_buffer(); 293 } 294 295 void MockTransferBuffer::FreePendingToken(void* p, unsigned int /* token */) { 296 EXPECT_EQ(last_alloc_, p); 297 last_alloc_ = NULL; 298 } 299 300 class GLES2ImplementationTest : public testing::Test { 301 protected: 302 static const uint8 kInitialValue = 0xBD; 303 static const int32 kNumCommandEntries = 500; 304 static const int32 kCommandBufferSizeBytes = 305 kNumCommandEntries * sizeof(CommandBufferEntry); 306 static const size_t kTransferBufferSize = 512; 307 308 static const GLint kMaxCombinedTextureImageUnits = 8; 309 static const GLint kMaxCubeMapTextureSize = 64; 310 static const GLint kMaxFragmentUniformVectors = 16; 311 static const GLint kMaxRenderbufferSize = 64; 312 static const GLint kMaxTextureImageUnits = 8; 313 static const GLint kMaxTextureSize = 128; 314 static const GLint kMaxVaryingVectors = 8; 315 static const GLint kMaxVertexAttribs = 8; 316 static const GLint kMaxVertexTextureImageUnits = 0; 317 static const GLint kMaxVertexUniformVectors = 128; 318 static const GLint kNumCompressedTextureFormats = 0; 319 static const GLint kNumShaderBinaryFormats = 0; 320 static const GLuint kStartId = 1024; 321 static const GLuint kBuffersStartId = 322 GLES2Implementation::kClientSideArrayId + 2; 323 static const GLuint kFramebuffersStartId = 1; 324 static const GLuint kProgramsAndShadersStartId = 1; 325 static const GLuint kRenderbuffersStartId = 1; 326 static const GLuint kTexturesStartId = 1; 327 static const GLuint kQueriesStartId = 1; 328 static const GLuint kVertexArraysStartId = 1; 329 330 typedef MockTransferBuffer::ExpectedMemoryInfo ExpectedMemoryInfo; 331 332 GLES2ImplementationTest() 333 : commands_(NULL), 334 token_(0) { 335 } 336 337 virtual void SetUp() OVERRIDE; 338 virtual void TearDown() OVERRIDE; 339 340 bool NoCommandsWritten() { 341 Buffer ring_buffer = helper_->get_ring_buffer(); 342 const uint8* cmds = reinterpret_cast<const uint8*>(ring_buffer.ptr); 343 const uint8* end = cmds + ring_buffer.size; 344 for (; cmds < end; ++cmds) { 345 if (*cmds != kInitialValue) { 346 return false; 347 } 348 } 349 return true; 350 } 351 352 QueryTracker::Query* GetQuery(GLuint id) { 353 return gl_->query_tracker_->GetQuery(id); 354 } 355 356 void Initialize(bool bind_generates_resource) { 357 command_buffer_.reset(new StrictMock<MockClientCommandBuffer>()); 358 ASSERT_TRUE(command_buffer_->Initialize()); 359 360 transfer_buffer_.reset(new MockTransferBuffer( 361 command_buffer(), 362 kTransferBufferSize, 363 GLES2Implementation::kStartingOffset, 364 GLES2Implementation::kAlignment)); 365 366 helper_.reset(new GLES2CmdHelper(command_buffer())); 367 helper_->Initialize(kCommandBufferSizeBytes); 368 369 GLES2Implementation::GLStaticState state; 370 GLES2Implementation::GLStaticState::IntState& int_state = state.int_state; 371 int_state.max_combined_texture_image_units = kMaxCombinedTextureImageUnits; 372 int_state.max_cube_map_texture_size = kMaxCubeMapTextureSize; 373 int_state.max_fragment_uniform_vectors = kMaxFragmentUniformVectors; 374 int_state.max_renderbuffer_size = kMaxRenderbufferSize; 375 int_state.max_texture_image_units = kMaxTextureImageUnits; 376 int_state.max_texture_size = kMaxTextureSize; 377 int_state.max_varying_vectors = kMaxVaryingVectors; 378 int_state.max_vertex_attribs = kMaxVertexAttribs; 379 int_state.max_vertex_texture_image_units = kMaxVertexTextureImageUnits; 380 int_state.max_vertex_uniform_vectors = kMaxVertexUniformVectors; 381 int_state.num_compressed_texture_formats = kNumCompressedTextureFormats; 382 int_state.num_shader_binary_formats = kNumShaderBinaryFormats; 383 384 // This just happens to work for now because IntState has 1 GLint per state. 385 // If IntState gets more complicated this code will need to get more 386 // complicated. 387 ExpectedMemoryInfo mem1 = GetExpectedMemory( 388 sizeof(GLES2Implementation::GLStaticState::IntState) * 2 + 389 sizeof(cmds::GetShaderPrecisionFormat::Result) * 12); 390 391 { 392 InSequence sequence; 393 394 EXPECT_CALL(*command_buffer(), OnFlush()) 395 .WillOnce(SetMemory(mem1.ptr + sizeof(int_state), int_state)) 396 .RetiresOnSaturation(); 397 GetNextToken(); // eat the token that starting up will use. 398 399 gl_.reset(new GLES2Implementation( 400 helper_.get(), 401 NULL, 402 transfer_buffer_.get(), 403 bind_generates_resource, 404 NULL)); 405 ASSERT_TRUE(gl_->Initialize( 406 kTransferBufferSize, 407 kTransferBufferSize, 408 kTransferBufferSize)); 409 } 410 411 EXPECT_CALL(*command_buffer(), OnFlush()) 412 .Times(1) 413 .RetiresOnSaturation(); 414 helper_->CommandBufferHelper::Finish(); 415 ::testing::Mock::VerifyAndClearExpectations(gl_.get()); 416 417 Buffer ring_buffer = helper_->get_ring_buffer(); 418 commands_ = static_cast<CommandBufferEntry*>(ring_buffer.ptr) + 419 command_buffer()->GetState().put_offset; 420 ClearCommands(); 421 EXPECT_TRUE(transfer_buffer_->InSync()); 422 423 ::testing::Mock::VerifyAndClearExpectations(command_buffer()); 424 } 425 426 MockClientCommandBuffer* command_buffer() const { 427 return command_buffer_.get(); 428 } 429 430 int GetNextToken() { 431 return ++token_; 432 } 433 434 const void* GetPut() { 435 return helper_->GetSpace(0); 436 } 437 438 void ClearCommands() { 439 Buffer ring_buffer = helper_->get_ring_buffer(); 440 memset(ring_buffer.ptr, kInitialValue, ring_buffer.size); 441 } 442 443 size_t MaxTransferBufferSize() { 444 return transfer_buffer_->MaxTransferBufferSize(); 445 } 446 447 ExpectedMemoryInfo GetExpectedMemory(size_t size) { 448 return transfer_buffer_->GetExpectedMemory(size); 449 } 450 451 ExpectedMemoryInfo GetExpectedResultMemory(size_t size) { 452 return transfer_buffer_->GetExpectedResultMemory(size); 453 } 454 455 // Sets the ProgramInfoManager. The manager will be owned 456 // by the ShareGroup. 457 void SetProgramInfoManager(ProgramInfoManager* manager) { 458 gl_->share_group()->set_program_info_manager(manager); 459 } 460 461 int CheckError() { 462 ExpectedMemoryInfo result = 463 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 464 EXPECT_CALL(*command_buffer(), OnFlush()) 465 .WillOnce(SetMemory(result.ptr, GLuint(GL_NO_ERROR))) 466 .RetiresOnSaturation(); 467 return gl_->GetError(); 468 } 469 470 bool GetBucketContents(uint32 bucket_id, std::vector<int8>* data) { 471 return gl_->GetBucketContents(bucket_id, data); 472 } 473 474 Sequence sequence_; 475 scoped_ptr<MockClientCommandBuffer> command_buffer_; 476 scoped_ptr<GLES2CmdHelper> helper_; 477 scoped_ptr<MockTransferBuffer> transfer_buffer_; 478 scoped_ptr<GLES2Implementation> gl_; 479 CommandBufferEntry* commands_; 480 int token_; 481 }; 482 483 void GLES2ImplementationTest::SetUp() { 484 Initialize(true); 485 } 486 487 void GLES2ImplementationTest::TearDown() { 488 Mock::VerifyAndClear(gl_.get()); 489 EXPECT_CALL(*command_buffer(), OnFlush()).Times(AnyNumber()); 490 // For command buffer. 491 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 492 .Times(AtLeast(1)); 493 gl_.reset(); 494 } 495 496 class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest { 497 protected: 498 virtual void SetUp() OVERRIDE; 499 }; 500 501 void GLES2ImplementationStrictSharedTest::SetUp() { 502 Initialize(false); 503 } 504 505 // GCC requires these declarations, but MSVC requires they not be present 506 #ifndef _MSC_VER 507 const uint8 GLES2ImplementationTest::kInitialValue; 508 const int32 GLES2ImplementationTest::kNumCommandEntries; 509 const int32 GLES2ImplementationTest::kCommandBufferSizeBytes; 510 const size_t GLES2ImplementationTest::kTransferBufferSize; 511 const GLint GLES2ImplementationTest::kMaxCombinedTextureImageUnits; 512 const GLint GLES2ImplementationTest::kMaxCubeMapTextureSize; 513 const GLint GLES2ImplementationTest::kMaxFragmentUniformVectors; 514 const GLint GLES2ImplementationTest::kMaxRenderbufferSize; 515 const GLint GLES2ImplementationTest::kMaxTextureImageUnits; 516 const GLint GLES2ImplementationTest::kMaxTextureSize; 517 const GLint GLES2ImplementationTest::kMaxVaryingVectors; 518 const GLint GLES2ImplementationTest::kMaxVertexAttribs; 519 const GLint GLES2ImplementationTest::kMaxVertexTextureImageUnits; 520 const GLint GLES2ImplementationTest::kMaxVertexUniformVectors; 521 const GLint GLES2ImplementationTest::kNumCompressedTextureFormats; 522 const GLint GLES2ImplementationTest::kNumShaderBinaryFormats; 523 const GLuint GLES2ImplementationTest::kStartId; 524 const GLuint GLES2ImplementationTest::kBuffersStartId; 525 const GLuint GLES2ImplementationTest::kFramebuffersStartId; 526 const GLuint GLES2ImplementationTest::kProgramsAndShadersStartId; 527 const GLuint GLES2ImplementationTest::kRenderbuffersStartId; 528 const GLuint GLES2ImplementationTest::kTexturesStartId; 529 const GLuint GLES2ImplementationTest::kQueriesStartId; 530 const GLuint GLES2ImplementationTest::kVertexArraysStartId; 531 #endif 532 533 TEST_F(GLES2ImplementationTest, Basic) { 534 EXPECT_TRUE(gl_->share_group() != NULL); 535 } 536 537 TEST_F(GLES2ImplementationTest, GetBucketContents) { 538 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 539 const uint32 kTestSize = MaxTransferBufferSize() + 32; 540 541 scoped_ptr<uint8[]> buf(new uint8 [kTestSize]); 542 uint8* expected_data = buf.get(); 543 for (uint32 ii = 0; ii < kTestSize; ++ii) { 544 expected_data[ii] = ii * 3; 545 } 546 547 struct Cmds { 548 cmd::GetBucketStart get_bucket_start; 549 cmd::SetToken set_token1; 550 cmd::GetBucketData get_bucket_data; 551 cmd::SetToken set_token2; 552 cmd::SetBucketSize set_bucket_size2; 553 }; 554 555 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 556 ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32)); 557 ExpectedMemoryInfo mem2 = GetExpectedMemory( 558 kTestSize - MaxTransferBufferSize()); 559 560 Cmds expected; 561 expected.get_bucket_start.Init( 562 kBucketId, result1.id, result1.offset, 563 MaxTransferBufferSize(), mem1.id, mem1.offset); 564 expected.set_token1.Init(GetNextToken()); 565 expected.get_bucket_data.Init( 566 kBucketId, MaxTransferBufferSize(), 567 kTestSize - MaxTransferBufferSize(), mem2.id, mem2.offset); 568 expected.set_bucket_size2.Init(kBucketId, 0); 569 expected.set_token2.Init(GetNextToken()); 570 571 EXPECT_CALL(*command_buffer(), OnFlush()) 572 .WillOnce(DoAll( 573 SetMemory(result1.ptr, kTestSize), 574 SetMemoryFromArray( 575 mem1.ptr, expected_data, MaxTransferBufferSize()))) 576 .WillOnce(SetMemoryFromArray( 577 mem2.ptr, expected_data + MaxTransferBufferSize(), 578 kTestSize - MaxTransferBufferSize())) 579 .RetiresOnSaturation(); 580 581 std::vector<int8> data; 582 GetBucketContents(kBucketId, &data); 583 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 584 ASSERT_EQ(kTestSize, data.size()); 585 EXPECT_EQ(0, memcmp(expected_data, &data[0], data.size())); 586 } 587 588 TEST_F(GLES2ImplementationTest, GetShaderPrecisionFormat) { 589 struct Cmds { 590 cmds::GetShaderPrecisionFormat cmd; 591 }; 592 typedef cmds::GetShaderPrecisionFormat::Result Result; 593 594 // The first call for mediump should trigger a command buffer request. 595 GLint range1[2] = {0, 0}; 596 GLint precision1 = 0; 597 Cmds expected1; 598 ExpectedMemoryInfo client_result1 = GetExpectedResultMemory(4); 599 expected1.cmd.Init(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, 600 client_result1.id, client_result1.offset); 601 Result server_result1 = {true, 14, 14, 10}; 602 EXPECT_CALL(*command_buffer(), OnFlush()) 603 .WillOnce(SetMemory(client_result1.ptr, server_result1)) 604 .RetiresOnSaturation(); 605 gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, 606 range1, &precision1); 607 const void* commands2 = GetPut(); 608 EXPECT_NE(commands_, commands2); 609 EXPECT_EQ(0, memcmp(&expected1, commands_, sizeof(expected1))); 610 EXPECT_EQ(range1[0], 14); 611 EXPECT_EQ(range1[1], 14); 612 EXPECT_EQ(precision1, 10); 613 614 // The second call for mediump should use the cached value and avoid 615 // triggering a command buffer request, so we do not expect a call to 616 // OnFlush() here. We do expect the results to be correct though. 617 GLint range2[2] = {0, 0}; 618 GLint precision2 = 0; 619 gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, 620 range2, &precision2); 621 const void* commands3 = GetPut(); 622 EXPECT_EQ(commands2, commands3); 623 EXPECT_EQ(range2[0], 14); 624 EXPECT_EQ(range2[1], 14); 625 EXPECT_EQ(precision2, 10); 626 627 // If we then make a request for highp, we should get another command 628 // buffer request since it hasn't been cached yet. 629 GLint range3[2] = {0, 0}; 630 GLint precision3 = 0; 631 Cmds expected3; 632 ExpectedMemoryInfo result3 = GetExpectedResultMemory(4); 633 expected3.cmd.Init(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, 634 result3.id, result3.offset); 635 Result result3_source = {true, 62, 62, 16}; 636 EXPECT_CALL(*command_buffer(), OnFlush()) 637 .WillOnce(SetMemory(result3.ptr, result3_source)) 638 .RetiresOnSaturation(); 639 gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, 640 range3, &precision3); 641 const void* commands4 = GetPut(); 642 EXPECT_NE(commands3, commands4); 643 EXPECT_EQ(0, memcmp(&expected3, commands3, sizeof(expected3))); 644 EXPECT_EQ(range3[0], 62); 645 EXPECT_EQ(range3[1], 62); 646 EXPECT_EQ(precision3, 16); 647 } 648 649 TEST_F(GLES2ImplementationTest, ShaderSource) { 650 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 651 const GLuint kShaderId = 456; 652 const char* kString1 = "foobar"; 653 const char* kString2 = "barfoo"; 654 const size_t kString1Size = strlen(kString1); 655 const size_t kString2Size = strlen(kString2); 656 const size_t kString3Size = 1; // Want the NULL; 657 const size_t kSourceSize = kString1Size + kString2Size + kString3Size; 658 const size_t kPaddedString1Size = 659 transfer_buffer_->RoundToAlignment(kString1Size); 660 const size_t kPaddedString2Size = 661 transfer_buffer_->RoundToAlignment(kString2Size); 662 const size_t kPaddedString3Size = 663 transfer_buffer_->RoundToAlignment(kString3Size); 664 struct Cmds { 665 cmd::SetBucketSize set_bucket_size; 666 cmd::SetBucketData set_bucket_data1; 667 cmd::SetToken set_token1; 668 cmd::SetBucketData set_bucket_data2; 669 cmd::SetToken set_token2; 670 cmd::SetBucketData set_bucket_data3; 671 cmd::SetToken set_token3; 672 cmds::ShaderSourceBucket shader_source_bucket; 673 cmd::SetBucketSize clear_bucket_size; 674 }; 675 676 ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); 677 ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); 678 ExpectedMemoryInfo mem3 = GetExpectedMemory(kPaddedString3Size); 679 680 Cmds expected; 681 expected.set_bucket_size.Init(kBucketId, kSourceSize); 682 expected.set_bucket_data1.Init( 683 kBucketId, 0, kString1Size, mem1.id, mem1.offset); 684 expected.set_token1.Init(GetNextToken()); 685 expected.set_bucket_data2.Init( 686 kBucketId, kString1Size, kString2Size, mem2.id, mem2.offset); 687 expected.set_token2.Init(GetNextToken()); 688 expected.set_bucket_data3.Init( 689 kBucketId, kString1Size + kString2Size, 690 kString3Size, mem3.id, mem3.offset); 691 expected.set_token3.Init(GetNextToken()); 692 expected.shader_source_bucket.Init(kShaderId, kBucketId); 693 expected.clear_bucket_size.Init(kBucketId, 0); 694 const char* strings[] = { 695 kString1, 696 kString2, 697 }; 698 gl_->ShaderSource(kShaderId, 2, strings, NULL); 699 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 700 } 701 702 TEST_F(GLES2ImplementationTest, GetShaderSource) { 703 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 704 const GLuint kShaderId = 456; 705 const Str7 kString = {"foobar"}; 706 const char kBad = 0x12; 707 struct Cmds { 708 cmd::SetBucketSize set_bucket_size1; 709 cmds::GetShaderSource get_shader_source; 710 cmd::GetBucketStart get_bucket_start; 711 cmd::SetToken set_token1; 712 cmd::SetBucketSize set_bucket_size2; 713 }; 714 715 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 716 ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32)); 717 718 Cmds expected; 719 expected.set_bucket_size1.Init(kBucketId, 0); 720 expected.get_shader_source.Init(kShaderId, kBucketId); 721 expected.get_bucket_start.Init( 722 kBucketId, result1.id, result1.offset, 723 MaxTransferBufferSize(), mem1.id, mem1.offset); 724 expected.set_token1.Init(GetNextToken()); 725 expected.set_bucket_size2.Init(kBucketId, 0); 726 char buf[sizeof(kString) + 1]; 727 memset(buf, kBad, sizeof(buf)); 728 729 EXPECT_CALL(*command_buffer(), OnFlush()) 730 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 731 SetMemory(mem1.ptr, kString))) 732 .RetiresOnSaturation(); 733 734 GLsizei length = 0; 735 gl_->GetShaderSource(kShaderId, sizeof(buf), &length, buf); 736 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 737 EXPECT_EQ(sizeof(kString) - 1, static_cast<size_t>(length)); 738 EXPECT_STREQ(kString.str, buf); 739 EXPECT_EQ(buf[sizeof(kString)], kBad); 740 } 741 742 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 743 744 TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) { 745 static const float verts[][4] = { 746 { 12.0f, 23.0f, 34.0f, 45.0f, }, 747 { 56.0f, 67.0f, 78.0f, 89.0f, }, 748 { 13.0f, 24.0f, 35.0f, 46.0f, }, 749 }; 750 struct Cmds { 751 cmds::EnableVertexAttribArray enable1; 752 cmds::EnableVertexAttribArray enable2; 753 cmds::BindBuffer bind_to_emu; 754 cmds::BufferData set_size; 755 cmds::BufferSubData copy_data1; 756 cmd::SetToken set_token1; 757 cmds::VertexAttribPointer set_pointer1; 758 cmds::BufferSubData copy_data2; 759 cmd::SetToken set_token2; 760 cmds::VertexAttribPointer set_pointer2; 761 cmds::DrawArrays draw; 762 cmds::BindBuffer restore; 763 }; 764 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 765 const GLuint kAttribIndex1 = 1; 766 const GLuint kAttribIndex2 = 3; 767 const GLint kNumComponents1 = 3; 768 const GLint kNumComponents2 = 2; 769 const GLsizei kClientStride = sizeof(verts[0]); 770 const GLint kFirst = 1; 771 const GLsizei kCount = 2; 772 const GLsizei kSize1 = 773 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 774 const GLsizei kSize2 = 775 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 776 const GLsizei kEmuOffset1 = 0; 777 const GLsizei kEmuOffset2 = kSize1; 778 const GLsizei kTotalSize = kSize1 + kSize2; 779 780 ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1); 781 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2); 782 783 Cmds expected; 784 expected.enable1.Init(kAttribIndex1); 785 expected.enable2.Init(kAttribIndex2); 786 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 787 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 788 expected.copy_data1.Init( 789 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset); 790 expected.set_token1.Init(GetNextToken()); 791 expected.set_pointer1.Init( 792 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 793 expected.copy_data2.Init( 794 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset); 795 expected.set_token2.Init(GetNextToken()); 796 expected.set_pointer2.Init( 797 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 798 expected.draw.Init(GL_POINTS, kFirst, kCount); 799 expected.restore.Init(GL_ARRAY_BUFFER, 0); 800 gl_->EnableVertexAttribArray(kAttribIndex1); 801 gl_->EnableVertexAttribArray(kAttribIndex2); 802 gl_->VertexAttribPointer( 803 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts); 804 gl_->VertexAttribPointer( 805 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts); 806 gl_->DrawArrays(GL_POINTS, kFirst, kCount); 807 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 808 } 809 810 TEST_F(GLES2ImplementationTest, DrawArraysInstancedANGLEClientSideBuffers) { 811 static const float verts[][4] = { 812 { 12.0f, 23.0f, 34.0f, 45.0f, }, 813 { 56.0f, 67.0f, 78.0f, 89.0f, }, 814 { 13.0f, 24.0f, 35.0f, 46.0f, }, 815 }; 816 struct Cmds { 817 cmds::EnableVertexAttribArray enable1; 818 cmds::EnableVertexAttribArray enable2; 819 cmds::VertexAttribDivisorANGLE divisor; 820 cmds::BindBuffer bind_to_emu; 821 cmds::BufferData set_size; 822 cmds::BufferSubData copy_data1; 823 cmd::SetToken set_token1; 824 cmds::VertexAttribPointer set_pointer1; 825 cmds::BufferSubData copy_data2; 826 cmd::SetToken set_token2; 827 cmds::VertexAttribPointer set_pointer2; 828 cmds::DrawArraysInstancedANGLE draw; 829 cmds::BindBuffer restore; 830 }; 831 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 832 const GLuint kAttribIndex1 = 1; 833 const GLuint kAttribIndex2 = 3; 834 const GLint kNumComponents1 = 3; 835 const GLint kNumComponents2 = 2; 836 const GLsizei kClientStride = sizeof(verts[0]); 837 const GLint kFirst = 1; 838 const GLsizei kCount = 2; 839 const GLuint kDivisor = 1; 840 const GLsizei kSize1 = 841 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 842 const GLsizei kSize2 = 843 1 * kNumComponents2 * sizeof(verts[0][0]); 844 const GLsizei kEmuOffset1 = 0; 845 const GLsizei kEmuOffset2 = kSize1; 846 const GLsizei kTotalSize = kSize1 + kSize2; 847 848 ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1); 849 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2); 850 851 Cmds expected; 852 expected.enable1.Init(kAttribIndex1); 853 expected.enable2.Init(kAttribIndex2); 854 expected.divisor.Init(kAttribIndex2, kDivisor); 855 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 856 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 857 expected.copy_data1.Init( 858 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset); 859 expected.set_token1.Init(GetNextToken()); 860 expected.set_pointer1.Init( 861 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 862 expected.copy_data2.Init( 863 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset); 864 expected.set_token2.Init(GetNextToken()); 865 expected.set_pointer2.Init( 866 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 867 expected.draw.Init(GL_POINTS, kFirst, kCount, 1); 868 expected.restore.Init(GL_ARRAY_BUFFER, 0); 869 gl_->EnableVertexAttribArray(kAttribIndex1); 870 gl_->EnableVertexAttribArray(kAttribIndex2); 871 gl_->VertexAttribPointer( 872 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts); 873 gl_->VertexAttribPointer( 874 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts); 875 gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor); 876 gl_->DrawArraysInstancedANGLE(GL_POINTS, kFirst, kCount, 1); 877 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 878 } 879 880 TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) { 881 static const float verts[][4] = { 882 { 12.0f, 23.0f, 34.0f, 45.0f, }, 883 { 56.0f, 67.0f, 78.0f, 89.0f, }, 884 { 13.0f, 24.0f, 35.0f, 46.0f, }, 885 }; 886 static const uint16 indices[] = { 887 1, 2, 888 }; 889 struct Cmds { 890 cmds::EnableVertexAttribArray enable1; 891 cmds::EnableVertexAttribArray enable2; 892 cmds::BindBuffer bind_to_index_emu; 893 cmds::BufferData set_index_size; 894 cmds::BufferSubData copy_data0; 895 cmd::SetToken set_token0; 896 cmds::BindBuffer bind_to_emu; 897 cmds::BufferData set_size; 898 cmds::BufferSubData copy_data1; 899 cmd::SetToken set_token1; 900 cmds::VertexAttribPointer set_pointer1; 901 cmds::BufferSubData copy_data2; 902 cmd::SetToken set_token2; 903 cmds::VertexAttribPointer set_pointer2; 904 cmds::DrawElements draw; 905 cmds::BindBuffer restore; 906 cmds::BindBuffer restore_element; 907 }; 908 const GLsizei kIndexSize = sizeof(indices); 909 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 910 const GLuint kEmuIndexBufferId = 911 GLES2Implementation::kClientSideElementArrayId; 912 const GLuint kAttribIndex1 = 1; 913 const GLuint kAttribIndex2 = 3; 914 const GLint kNumComponents1 = 3; 915 const GLint kNumComponents2 = 2; 916 const GLsizei kClientStride = sizeof(verts[0]); 917 const GLsizei kCount = 2; 918 const GLsizei kSize1 = 919 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 920 const GLsizei kSize2 = 921 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 922 const GLsizei kEmuOffset1 = 0; 923 const GLsizei kEmuOffset2 = kSize1; 924 const GLsizei kTotalSize = kSize1 + kSize2; 925 926 ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); 927 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 928 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 929 930 Cmds expected; 931 expected.enable1.Init(kAttribIndex1); 932 expected.enable2.Init(kAttribIndex2); 933 expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); 934 expected.set_index_size.Init( 935 GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); 936 expected.copy_data0.Init( 937 GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); 938 expected.set_token0.Init(GetNextToken()); 939 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 940 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 941 expected.copy_data1.Init( 942 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 943 expected.set_token1.Init(GetNextToken()); 944 expected.set_pointer1.Init( 945 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 946 expected.copy_data2.Init( 947 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 948 expected.set_token2.Init(GetNextToken()); 949 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 950 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 951 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0); 952 expected.restore.Init(GL_ARRAY_BUFFER, 0); 953 expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); 954 gl_->EnableVertexAttribArray(kAttribIndex1); 955 gl_->EnableVertexAttribArray(kAttribIndex2); 956 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 957 GL_FLOAT, GL_FALSE, kClientStride, verts); 958 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 959 GL_FLOAT, GL_FALSE, kClientStride, verts); 960 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices); 961 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 962 } 963 964 TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersIndexUint) { 965 static const float verts[][4] = { 966 { 12.0f, 23.0f, 34.0f, 45.0f, }, 967 { 56.0f, 67.0f, 78.0f, 89.0f, }, 968 { 13.0f, 24.0f, 35.0f, 46.0f, }, 969 }; 970 static const uint32 indices[] = { 971 1, 2, 972 }; 973 struct Cmds { 974 cmds::EnableVertexAttribArray enable1; 975 cmds::EnableVertexAttribArray enable2; 976 cmds::BindBuffer bind_to_index_emu; 977 cmds::BufferData set_index_size; 978 cmds::BufferSubData copy_data0; 979 cmd::SetToken set_token0; 980 cmds::BindBuffer bind_to_emu; 981 cmds::BufferData set_size; 982 cmds::BufferSubData copy_data1; 983 cmd::SetToken set_token1; 984 cmds::VertexAttribPointer set_pointer1; 985 cmds::BufferSubData copy_data2; 986 cmd::SetToken set_token2; 987 cmds::VertexAttribPointer set_pointer2; 988 cmds::DrawElements draw; 989 cmds::BindBuffer restore; 990 cmds::BindBuffer restore_element; 991 }; 992 const GLsizei kIndexSize = sizeof(indices); 993 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 994 const GLuint kEmuIndexBufferId = 995 GLES2Implementation::kClientSideElementArrayId; 996 const GLuint kAttribIndex1 = 1; 997 const GLuint kAttribIndex2 = 3; 998 const GLint kNumComponents1 = 3; 999 const GLint kNumComponents2 = 2; 1000 const GLsizei kClientStride = sizeof(verts[0]); 1001 const GLsizei kCount = 2; 1002 const GLsizei kSize1 = 1003 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1004 const GLsizei kSize2 = 1005 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 1006 const GLsizei kEmuOffset1 = 0; 1007 const GLsizei kEmuOffset2 = kSize1; 1008 const GLsizei kTotalSize = kSize1 + kSize2; 1009 1010 ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); 1011 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1012 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1013 1014 Cmds expected; 1015 expected.enable1.Init(kAttribIndex1); 1016 expected.enable2.Init(kAttribIndex2); 1017 expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); 1018 expected.set_index_size.Init( 1019 GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); 1020 expected.copy_data0.Init( 1021 GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); 1022 expected.set_token0.Init(GetNextToken()); 1023 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1024 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1025 expected.copy_data1.Init( 1026 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1027 expected.set_token1.Init(GetNextToken()); 1028 expected.set_pointer1.Init( 1029 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1030 expected.copy_data2.Init( 1031 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1032 expected.set_token2.Init(GetNextToken()); 1033 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1034 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1035 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_INT, 0); 1036 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1037 expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); 1038 gl_->EnableVertexAttribArray(kAttribIndex1); 1039 gl_->EnableVertexAttribArray(kAttribIndex2); 1040 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1041 GL_FLOAT, GL_FALSE, kClientStride, verts); 1042 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1043 GL_FLOAT, GL_FALSE, kClientStride, verts); 1044 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices); 1045 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1046 } 1047 1048 TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersInvalidIndexUint) { 1049 static const float verts[][4] = { 1050 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1051 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1052 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1053 }; 1054 static const uint32 indices[] = { 1055 1, 0x90000000 1056 }; 1057 1058 const GLuint kAttribIndex1 = 1; 1059 const GLuint kAttribIndex2 = 3; 1060 const GLint kNumComponents1 = 3; 1061 const GLint kNumComponents2 = 2; 1062 const GLsizei kClientStride = sizeof(verts[0]); 1063 const GLsizei kCount = 2; 1064 1065 EXPECT_CALL(*command_buffer(), OnFlush()) 1066 .Times(1) 1067 .RetiresOnSaturation(); 1068 1069 gl_->EnableVertexAttribArray(kAttribIndex1); 1070 gl_->EnableVertexAttribArray(kAttribIndex2); 1071 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1072 GL_FLOAT, GL_FALSE, kClientStride, verts); 1073 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1074 GL_FLOAT, GL_FALSE, kClientStride, verts); 1075 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices); 1076 1077 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError()); 1078 } 1079 1080 TEST_F(GLES2ImplementationTest, 1081 DrawElementsClientSideBuffersServiceSideIndices) { 1082 static const float verts[][4] = { 1083 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1084 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1085 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1086 }; 1087 struct Cmds { 1088 cmds::EnableVertexAttribArray enable1; 1089 cmds::EnableVertexAttribArray enable2; 1090 cmds::BindBuffer bind_to_index; 1091 cmds::GetMaxValueInBufferCHROMIUM get_max; 1092 cmds::BindBuffer bind_to_emu; 1093 cmds::BufferData set_size; 1094 cmds::BufferSubData copy_data1; 1095 cmd::SetToken set_token1; 1096 cmds::VertexAttribPointer set_pointer1; 1097 cmds::BufferSubData copy_data2; 1098 cmd::SetToken set_token2; 1099 cmds::VertexAttribPointer set_pointer2; 1100 cmds::DrawElements draw; 1101 cmds::BindBuffer restore; 1102 }; 1103 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1104 const GLuint kClientIndexBufferId = 0x789; 1105 const GLuint kIndexOffset = 0x40; 1106 const GLuint kMaxIndex = 2; 1107 const GLuint kAttribIndex1 = 1; 1108 const GLuint kAttribIndex2 = 3; 1109 const GLint kNumComponents1 = 3; 1110 const GLint kNumComponents2 = 2; 1111 const GLsizei kClientStride = sizeof(verts[0]); 1112 const GLsizei kCount = 2; 1113 const GLsizei kSize1 = 1114 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1115 const GLsizei kSize2 = 1116 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 1117 const GLsizei kEmuOffset1 = 0; 1118 const GLsizei kEmuOffset2 = kSize1; 1119 const GLsizei kTotalSize = kSize1 + kSize2; 1120 1121 ExpectedMemoryInfo mem1 = GetExpectedResultMemory(sizeof(uint32)); 1122 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1123 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1124 1125 1126 Cmds expected; 1127 expected.enable1.Init(kAttribIndex1); 1128 expected.enable2.Init(kAttribIndex2); 1129 expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); 1130 expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT, 1131 kIndexOffset, mem1.id, mem1.offset); 1132 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1133 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1134 expected.copy_data1.Init( 1135 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1136 expected.set_token1.Init(GetNextToken()); 1137 expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, 1138 GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1139 expected.copy_data2.Init( 1140 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1141 expected.set_token2.Init(GetNextToken()); 1142 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1143 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1144 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, kIndexOffset); 1145 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1146 1147 EXPECT_CALL(*command_buffer(), OnFlush()) 1148 .WillOnce(SetMemory(mem1.ptr,kMaxIndex)) 1149 .RetiresOnSaturation(); 1150 1151 gl_->EnableVertexAttribArray(kAttribIndex1); 1152 gl_->EnableVertexAttribArray(kAttribIndex2); 1153 gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); 1154 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1155 GL_FLOAT, GL_FALSE, kClientStride, verts); 1156 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1157 GL_FLOAT, GL_FALSE, kClientStride, verts); 1158 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 1159 reinterpret_cast<const void*>(kIndexOffset)); 1160 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1161 } 1162 1163 TEST_F(GLES2ImplementationTest, DrawElementsInstancedANGLEClientSideBuffers) { 1164 static const float verts[][4] = { 1165 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1166 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1167 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1168 }; 1169 static const uint16 indices[] = { 1170 1, 2, 1171 }; 1172 struct Cmds { 1173 cmds::EnableVertexAttribArray enable1; 1174 cmds::EnableVertexAttribArray enable2; 1175 cmds::VertexAttribDivisorANGLE divisor; 1176 cmds::BindBuffer bind_to_index_emu; 1177 cmds::BufferData set_index_size; 1178 cmds::BufferSubData copy_data0; 1179 cmd::SetToken set_token0; 1180 cmds::BindBuffer bind_to_emu; 1181 cmds::BufferData set_size; 1182 cmds::BufferSubData copy_data1; 1183 cmd::SetToken set_token1; 1184 cmds::VertexAttribPointer set_pointer1; 1185 cmds::BufferSubData copy_data2; 1186 cmd::SetToken set_token2; 1187 cmds::VertexAttribPointer set_pointer2; 1188 cmds::DrawElementsInstancedANGLE draw; 1189 cmds::BindBuffer restore; 1190 cmds::BindBuffer restore_element; 1191 }; 1192 const GLsizei kIndexSize = sizeof(indices); 1193 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1194 const GLuint kEmuIndexBufferId = 1195 GLES2Implementation::kClientSideElementArrayId; 1196 const GLuint kAttribIndex1 = 1; 1197 const GLuint kAttribIndex2 = 3; 1198 const GLint kNumComponents1 = 3; 1199 const GLint kNumComponents2 = 2; 1200 const GLsizei kClientStride = sizeof(verts[0]); 1201 const GLsizei kCount = 2; 1202 const GLsizei kSize1 = 1203 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1204 const GLsizei kSize2 = 1205 1 * kNumComponents2 * sizeof(verts[0][0]); 1206 const GLuint kDivisor = 1; 1207 const GLsizei kEmuOffset1 = 0; 1208 const GLsizei kEmuOffset2 = kSize1; 1209 const GLsizei kTotalSize = kSize1 + kSize2; 1210 1211 ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); 1212 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1213 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1214 1215 Cmds expected; 1216 expected.enable1.Init(kAttribIndex1); 1217 expected.enable2.Init(kAttribIndex2); 1218 expected.divisor.Init(kAttribIndex2, kDivisor); 1219 expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); 1220 expected.set_index_size.Init( 1221 GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); 1222 expected.copy_data0.Init( 1223 GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); 1224 expected.set_token0.Init(GetNextToken()); 1225 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1226 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1227 expected.copy_data1.Init( 1228 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1229 expected.set_token1.Init(GetNextToken()); 1230 expected.set_pointer1.Init( 1231 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1232 expected.copy_data2.Init( 1233 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1234 expected.set_token2.Init(GetNextToken()); 1235 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1236 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1237 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0, 1); 1238 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1239 expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); 1240 gl_->EnableVertexAttribArray(kAttribIndex1); 1241 gl_->EnableVertexAttribArray(kAttribIndex2); 1242 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1243 GL_FLOAT, GL_FALSE, kClientStride, verts); 1244 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1245 GL_FLOAT, GL_FALSE, kClientStride, verts); 1246 gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor); 1247 gl_->DrawElementsInstancedANGLE( 1248 GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices, 1); 1249 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1250 } 1251 1252 TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) { 1253 static const float verts[1] = { 0.0f, }; 1254 const GLuint kAttribIndex1 = 1; 1255 const GLuint kAttribIndex2 = 3; 1256 const GLint kNumComponents1 = 3; 1257 const GLint kNumComponents2 = 2; 1258 const GLsizei kStride1 = 12; 1259 const GLsizei kStride2 = 0; 1260 const GLuint kBufferId = 0x123; 1261 const GLint kOffset2 = 0x456; 1262 1263 // It's all cached on the client side so no get commands are issued. 1264 struct Cmds { 1265 cmds::BindBuffer bind; 1266 cmds::VertexAttribPointer set_pointer; 1267 }; 1268 1269 Cmds expected; 1270 expected.bind.Init(GL_ARRAY_BUFFER, kBufferId); 1271 expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 1272 kStride2, kOffset2); 1273 1274 // Set one client side buffer. 1275 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1276 GL_FLOAT, GL_FALSE, kStride1, verts); 1277 // Set one VBO 1278 gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); 1279 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1280 GL_FLOAT, GL_FALSE, kStride2, 1281 reinterpret_cast<const void*>(kOffset2)); 1282 // now get them both. 1283 void* ptr1 = NULL; 1284 void* ptr2 = NULL; 1285 1286 gl_->GetVertexAttribPointerv( 1287 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr1); 1288 gl_->GetVertexAttribPointerv( 1289 kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr2); 1290 1291 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1292 EXPECT_TRUE(static_cast<const void*>(&verts) == ptr1); 1293 EXPECT_TRUE(ptr2 == reinterpret_cast<void*>(kOffset2)); 1294 } 1295 1296 TEST_F(GLES2ImplementationTest, GetVertexAttrib) { 1297 static const float verts[1] = { 0.0f, }; 1298 const GLuint kAttribIndex1 = 1; 1299 const GLuint kAttribIndex2 = 3; 1300 const GLint kNumComponents1 = 3; 1301 const GLint kNumComponents2 = 2; 1302 const GLsizei kStride1 = 12; 1303 const GLsizei kStride2 = 0; 1304 const GLuint kBufferId = 0x123; 1305 const GLint kOffset2 = 0x456; 1306 1307 // Only one set and one get because the client side buffer's info is stored 1308 // on the client side. 1309 struct Cmds { 1310 cmds::EnableVertexAttribArray enable; 1311 cmds::BindBuffer bind; 1312 cmds::VertexAttribPointer set_pointer; 1313 cmds::GetVertexAttribfv get2; // for getting the value from attrib1 1314 }; 1315 1316 ExpectedMemoryInfo mem2 = GetExpectedResultMemory(16); 1317 1318 Cmds expected; 1319 expected.enable.Init(kAttribIndex1); 1320 expected.bind.Init(GL_ARRAY_BUFFER, kBufferId); 1321 expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 1322 kStride2, kOffset2); 1323 expected.get2.Init(kAttribIndex1, 1324 GL_CURRENT_VERTEX_ATTRIB, 1325 mem2.id, mem2.offset); 1326 1327 FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f); 1328 1329 // One call to flush to wait for last call to GetVertexAttribiv 1330 // as others are all cached. 1331 EXPECT_CALL(*command_buffer(), OnFlush()) 1332 .WillOnce(SetMemory( 1333 mem2.ptr, SizedResultHelper<FourFloats>(current_attrib))) 1334 .RetiresOnSaturation(); 1335 1336 gl_->EnableVertexAttribArray(kAttribIndex1); 1337 // Set one client side buffer. 1338 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1339 GL_FLOAT, GL_FALSE, kStride1, verts); 1340 // Set one VBO 1341 gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); 1342 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1343 GL_FLOAT, GL_FALSE, kStride2, 1344 reinterpret_cast<const void*>(kOffset2)); 1345 // first get the service side once to see that we make a command 1346 GLint buffer_id = 0; 1347 GLint enabled = 0; 1348 GLint size = 0; 1349 GLint stride = 0; 1350 GLint type = 0; 1351 GLint normalized = 1; 1352 float current[4] = { 0.0f, }; 1353 1354 gl_->GetVertexAttribiv( 1355 kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id); 1356 EXPECT_EQ(kBufferId, static_cast<GLuint>(buffer_id)); 1357 gl_->GetVertexAttribiv( 1358 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id); 1359 gl_->GetVertexAttribiv( 1360 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled); 1361 gl_->GetVertexAttribiv( 1362 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size); 1363 gl_->GetVertexAttribiv( 1364 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride); 1365 gl_->GetVertexAttribiv( 1366 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type); 1367 gl_->GetVertexAttribiv( 1368 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized); 1369 gl_->GetVertexAttribfv( 1370 kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, ¤t[0]); 1371 1372 EXPECT_EQ(0, buffer_id); 1373 EXPECT_EQ(GL_TRUE, enabled); 1374 EXPECT_EQ(kNumComponents1, size); 1375 EXPECT_EQ(kStride1, stride); 1376 EXPECT_EQ(GL_FLOAT, type); 1377 EXPECT_EQ(GL_FALSE, normalized); 1378 EXPECT_EQ(0, memcmp(¤t_attrib, ¤t, sizeof(current_attrib))); 1379 1380 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1381 } 1382 1383 TEST_F(GLES2ImplementationTest, ReservedIds) { 1384 // Only the get error command should be issued. 1385 struct Cmds { 1386 cmds::GetError get; 1387 }; 1388 Cmds expected; 1389 1390 ExpectedMemoryInfo mem1 = GetExpectedResultMemory( 1391 sizeof(cmds::GetError::Result)); 1392 1393 expected.get.Init(mem1.id, mem1.offset); 1394 1395 // One call to flush to wait for GetError 1396 EXPECT_CALL(*command_buffer(), OnFlush()) 1397 .WillOnce(SetMemory(mem1.ptr, GLuint(GL_NO_ERROR))) 1398 .RetiresOnSaturation(); 1399 1400 gl_->BindBuffer( 1401 GL_ARRAY_BUFFER, 1402 GLES2Implementation::kClientSideArrayId); 1403 gl_->BindBuffer( 1404 GL_ARRAY_BUFFER, 1405 GLES2Implementation::kClientSideElementArrayId); 1406 GLenum err = gl_->GetError(); 1407 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), err); 1408 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1409 } 1410 1411 #endif // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 1412 1413 TEST_F(GLES2ImplementationTest, ReadPixels2Reads) { 1414 struct Cmds { 1415 cmds::ReadPixels read1; 1416 cmd::SetToken set_token1; 1417 cmds::ReadPixels read2; 1418 cmd::SetToken set_token2; 1419 }; 1420 const GLint kBytesPerPixel = 4; 1421 const GLint kWidth = 1422 (kTransferBufferSize - GLES2Implementation::kStartingOffset) / 1423 kBytesPerPixel; 1424 const GLint kHeight = 2; 1425 const GLenum kFormat = GL_RGBA; 1426 const GLenum kType = GL_UNSIGNED_BYTE; 1427 1428 ExpectedMemoryInfo mem1 = 1429 GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel); 1430 ExpectedMemoryInfo result1 = 1431 GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result)); 1432 ExpectedMemoryInfo mem2 = 1433 GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel); 1434 ExpectedMemoryInfo result2 = 1435 GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result)); 1436 1437 Cmds expected; 1438 expected.read1.Init( 1439 0, 0, kWidth, kHeight / 2, kFormat, kType, 1440 mem1.id, mem1.offset, result1.id, result1.offset, 1441 false); 1442 expected.set_token1.Init(GetNextToken()); 1443 expected.read2.Init( 1444 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, 1445 mem2.id, mem2.offset, result2.id, result2.offset, false); 1446 expected.set_token2.Init(GetNextToken()); 1447 scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]); 1448 1449 EXPECT_CALL(*command_buffer(), OnFlush()) 1450 .WillOnce(SetMemory(result1.ptr, static_cast<uint32>(1))) 1451 .WillOnce(SetMemory(result2.ptr, static_cast<uint32>(1))) 1452 .RetiresOnSaturation(); 1453 1454 gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get()); 1455 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1456 } 1457 1458 TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) { 1459 struct Cmds { 1460 cmds::ReadPixels read; 1461 cmd::SetToken set_token; 1462 }; 1463 const GLint kBytesPerPixel = 4; 1464 const GLint kWidth = 2; 1465 const GLint kHeight = 2; 1466 const GLenum kFormat = 0; 1467 const GLenum kType = 0; 1468 1469 ExpectedMemoryInfo mem1 = 1470 GetExpectedMemory(kWidth * kHeight * kBytesPerPixel); 1471 ExpectedMemoryInfo result1 = 1472 GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result)); 1473 1474 Cmds expected; 1475 expected.read.Init( 1476 0, 0, kWidth, kHeight, kFormat, kType, 1477 mem1.id, mem1.offset, result1.id, result1.offset, false); 1478 expected.set_token.Init(GetNextToken()); 1479 scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]); 1480 1481 EXPECT_CALL(*command_buffer(), OnFlush()) 1482 .Times(1) 1483 .RetiresOnSaturation(); 1484 1485 gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get()); 1486 } 1487 1488 TEST_F(GLES2ImplementationTest, FreeUnusedSharedMemory) { 1489 struct Cmds { 1490 cmds::BufferSubData buf; 1491 cmd::SetToken set_token; 1492 }; 1493 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; 1494 const GLintptr kOffset = 15; 1495 const GLsizeiptr kSize = 16; 1496 1497 ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize); 1498 1499 Cmds expected; 1500 expected.buf.Init( 1501 kTarget, kOffset, kSize, mem1.id, mem1.offset); 1502 expected.set_token.Init(GetNextToken()); 1503 1504 void* mem = gl_->MapBufferSubDataCHROMIUM( 1505 kTarget, kOffset, kSize, GL_WRITE_ONLY); 1506 ASSERT_TRUE(mem != NULL); 1507 gl_->UnmapBufferSubDataCHROMIUM(mem); 1508 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 1509 .Times(1) 1510 .RetiresOnSaturation(); 1511 gl_->FreeUnusedSharedMemory(); 1512 } 1513 1514 TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUM) { 1515 struct Cmds { 1516 cmds::BufferSubData buf; 1517 cmd::SetToken set_token; 1518 }; 1519 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; 1520 const GLintptr kOffset = 15; 1521 const GLsizeiptr kSize = 16; 1522 1523 uint32 offset = 0; 1524 Cmds expected; 1525 expected.buf.Init( 1526 kTarget, kOffset, kSize, 1527 command_buffer()->GetNextFreeTransferBufferId(), offset); 1528 expected.set_token.Init(GetNextToken()); 1529 1530 void* mem = gl_->MapBufferSubDataCHROMIUM( 1531 kTarget, kOffset, kSize, GL_WRITE_ONLY); 1532 ASSERT_TRUE(mem != NULL); 1533 gl_->UnmapBufferSubDataCHROMIUM(mem); 1534 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1535 } 1536 1537 TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUMBadArgs) { 1538 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; 1539 const GLintptr kOffset = 15; 1540 const GLsizeiptr kSize = 16; 1541 1542 ExpectedMemoryInfo result1 = 1543 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1544 ExpectedMemoryInfo result2 = 1545 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1546 ExpectedMemoryInfo result3 = 1547 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1548 ExpectedMemoryInfo result4 = 1549 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1550 1551 // Calls to flush to wait for GetError 1552 EXPECT_CALL(*command_buffer(), OnFlush()) 1553 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1554 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1555 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 1556 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 1557 .RetiresOnSaturation(); 1558 1559 void* mem; 1560 mem = gl_->MapBufferSubDataCHROMIUM(kTarget, -1, kSize, GL_WRITE_ONLY); 1561 ASSERT_TRUE(mem == NULL); 1562 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1563 mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, -1, GL_WRITE_ONLY); 1564 ASSERT_TRUE(mem == NULL); 1565 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1566 mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, kSize, GL_READ_ONLY); 1567 ASSERT_TRUE(mem == NULL); 1568 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError()); 1569 const char* kPtr = "something"; 1570 gl_->UnmapBufferSubDataCHROMIUM(kPtr); 1571 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1572 } 1573 1574 TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUM) { 1575 struct Cmds { 1576 cmds::TexSubImage2D tex; 1577 cmd::SetToken set_token; 1578 }; 1579 const GLint kLevel = 1; 1580 const GLint kXOffset = 2; 1581 const GLint kYOffset = 3; 1582 const GLint kWidth = 4; 1583 const GLint kHeight = 5; 1584 const GLenum kFormat = GL_RGBA; 1585 const GLenum kType = GL_UNSIGNED_BYTE; 1586 1587 uint32 offset = 0; 1588 Cmds expected; 1589 expected.tex.Init( 1590 GL_TEXTURE_2D, kLevel, kXOffset, kYOffset, kWidth, kHeight, kFormat, 1591 kType, 1592 command_buffer()->GetNextFreeTransferBufferId(), offset, GL_FALSE); 1593 expected.set_token.Init(GetNextToken()); 1594 1595 void* mem = gl_->MapTexSubImage2DCHROMIUM( 1596 GL_TEXTURE_2D, 1597 kLevel, 1598 kXOffset, 1599 kYOffset, 1600 kWidth, 1601 kHeight, 1602 kFormat, 1603 kType, 1604 GL_WRITE_ONLY); 1605 ASSERT_TRUE(mem != NULL); 1606 gl_->UnmapTexSubImage2DCHROMIUM(mem); 1607 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1608 } 1609 1610 TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUMBadArgs) { 1611 const GLint kLevel = 1; 1612 const GLint kXOffset = 2; 1613 const GLint kYOffset = 3; 1614 const GLint kWidth = 4; 1615 const GLint kHeight = 5; 1616 const GLenum kFormat = GL_RGBA; 1617 const GLenum kType = GL_UNSIGNED_BYTE; 1618 1619 ExpectedMemoryInfo result1 = 1620 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1621 ExpectedMemoryInfo result2 = 1622 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1623 ExpectedMemoryInfo result3 = 1624 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1625 ExpectedMemoryInfo result4 = 1626 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1627 ExpectedMemoryInfo result5 = 1628 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1629 ExpectedMemoryInfo result6 = 1630 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1631 ExpectedMemoryInfo result7 = 1632 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1633 1634 // Calls to flush to wait for GetError 1635 EXPECT_CALL(*command_buffer(), OnFlush()) 1636 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1637 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1638 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 1639 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 1640 .WillOnce(SetMemory(result5.ptr, GLuint(GL_NO_ERROR))) 1641 .WillOnce(SetMemory(result6.ptr, GLuint(GL_NO_ERROR))) 1642 .WillOnce(SetMemory(result7.ptr, GLuint(GL_NO_ERROR))) 1643 .RetiresOnSaturation(); 1644 1645 void* mem; 1646 mem = gl_->MapTexSubImage2DCHROMIUM( 1647 GL_TEXTURE_2D, 1648 -1, 1649 kXOffset, 1650 kYOffset, 1651 kWidth, 1652 kHeight, 1653 kFormat, 1654 kType, 1655 GL_WRITE_ONLY); 1656 EXPECT_TRUE(mem == NULL); 1657 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1658 mem = gl_->MapTexSubImage2DCHROMIUM( 1659 GL_TEXTURE_2D, 1660 kLevel, 1661 -1, 1662 kYOffset, 1663 kWidth, 1664 kHeight, 1665 kFormat, 1666 kType, 1667 GL_WRITE_ONLY); 1668 EXPECT_TRUE(mem == NULL); 1669 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1670 mem = gl_->MapTexSubImage2DCHROMIUM( 1671 GL_TEXTURE_2D, 1672 kLevel, 1673 kXOffset, 1674 -1, 1675 kWidth, 1676 kHeight, 1677 kFormat, 1678 kType, 1679 GL_WRITE_ONLY); 1680 EXPECT_TRUE(mem == NULL); 1681 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1682 mem = gl_->MapTexSubImage2DCHROMIUM( 1683 GL_TEXTURE_2D, 1684 kLevel, 1685 kXOffset, 1686 kYOffset, 1687 -1, 1688 kHeight, 1689 kFormat, 1690 kType, 1691 GL_WRITE_ONLY); 1692 EXPECT_TRUE(mem == NULL); 1693 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1694 mem = gl_->MapTexSubImage2DCHROMIUM( 1695 GL_TEXTURE_2D, 1696 kLevel, 1697 kXOffset, 1698 kYOffset, 1699 kWidth, 1700 -1, 1701 kFormat, 1702 kType, 1703 GL_WRITE_ONLY); 1704 EXPECT_TRUE(mem == NULL); 1705 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1706 mem = gl_->MapTexSubImage2DCHROMIUM( 1707 GL_TEXTURE_2D, 1708 kLevel, 1709 kXOffset, 1710 kYOffset, 1711 kWidth, 1712 kHeight, 1713 kFormat, 1714 kType, 1715 GL_READ_ONLY); 1716 EXPECT_TRUE(mem == NULL); 1717 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError()); 1718 const char* kPtr = "something"; 1719 gl_->UnmapTexSubImage2DCHROMIUM(kPtr); 1720 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1721 } 1722 1723 TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMValidArgs) { 1724 const GLenum pnames[] = { 1725 GL_DEPTH_WRITEMASK, 1726 GL_COLOR_WRITEMASK, 1727 GL_STENCIL_WRITEMASK, 1728 }; 1729 const GLint num_results = 6; 1730 GLint results[num_results + 1]; 1731 struct Cmds { 1732 cmds::GetMultipleIntegervCHROMIUM get_multiple; 1733 cmd::SetToken set_token; 1734 }; 1735 const GLsizei kNumPnames = arraysize(pnames); 1736 const GLsizeiptr kResultsSize = num_results * sizeof(results[0]); 1737 const size_t kPNamesSize = kNumPnames * sizeof(pnames[0]); 1738 1739 ExpectedMemoryInfo mem1 = GetExpectedMemory(kPNamesSize + kResultsSize); 1740 ExpectedMemoryInfo result1 = GetExpectedResultMemory( 1741 sizeof(cmds::GetError::Result)); 1742 1743 const uint32 kPnamesOffset = mem1.offset; 1744 const uint32 kResultsOffset = mem1.offset + kPNamesSize; 1745 Cmds expected; 1746 expected.get_multiple.Init( 1747 mem1.id, kPnamesOffset, kNumPnames, 1748 mem1.id, kResultsOffset, kResultsSize); 1749 expected.set_token.Init(GetNextToken()); 1750 1751 const GLint kSentinel = 0x12345678; 1752 memset(results, 0, sizeof(results)); 1753 results[num_results] = kSentinel; 1754 const GLint returned_results[] = { 1755 1, 0, 1, 0, 1, -1, 1756 }; 1757 // One call to flush to wait for results 1758 EXPECT_CALL(*command_buffer(), OnFlush()) 1759 .WillOnce(SetMemoryFromArray(mem1.ptr + kPNamesSize, 1760 returned_results, sizeof(returned_results))) 1761 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1762 .RetiresOnSaturation(); 1763 1764 gl_->GetMultipleIntegervCHROMIUM( 1765 &pnames[0], kNumPnames, &results[0], kResultsSize); 1766 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1767 EXPECT_EQ(0, memcmp(&returned_results, results, sizeof(returned_results))); 1768 EXPECT_EQ(kSentinel, results[num_results]); 1769 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 1770 } 1771 1772 TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMBadArgs) { 1773 GLenum pnames[] = { 1774 GL_DEPTH_WRITEMASK, 1775 GL_COLOR_WRITEMASK, 1776 GL_STENCIL_WRITEMASK, 1777 }; 1778 const GLint num_results = 6; 1779 GLint results[num_results + 1]; 1780 const GLsizei kNumPnames = arraysize(pnames); 1781 const GLsizeiptr kResultsSize = num_results * sizeof(results[0]); 1782 1783 ExpectedMemoryInfo result1 = 1784 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1785 ExpectedMemoryInfo result2 = 1786 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1787 ExpectedMemoryInfo result3 = 1788 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1789 ExpectedMemoryInfo result4 = 1790 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1791 1792 // Calls to flush to wait for GetError 1793 EXPECT_CALL(*command_buffer(), OnFlush()) 1794 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1795 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1796 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 1797 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 1798 .RetiresOnSaturation(); 1799 1800 const GLint kSentinel = 0x12345678; 1801 memset(results, 0, sizeof(results)); 1802 results[num_results] = kSentinel; 1803 // try bad size. 1804 gl_->GetMultipleIntegervCHROMIUM( 1805 &pnames[0], kNumPnames, &results[0], kResultsSize + 1); 1806 EXPECT_TRUE(NoCommandsWritten()); 1807 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1808 EXPECT_EQ(0, results[0]); 1809 EXPECT_EQ(kSentinel, results[num_results]); 1810 // try bad size. 1811 ClearCommands(); 1812 gl_->GetMultipleIntegervCHROMIUM( 1813 &pnames[0], kNumPnames, &results[0], kResultsSize - 1); 1814 EXPECT_TRUE(NoCommandsWritten()); 1815 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1816 EXPECT_EQ(0, results[0]); 1817 EXPECT_EQ(kSentinel, results[num_results]); 1818 // try uncleared results. 1819 ClearCommands(); 1820 results[2] = 1; 1821 gl_->GetMultipleIntegervCHROMIUM( 1822 &pnames[0], kNumPnames, &results[0], kResultsSize); 1823 EXPECT_TRUE(NoCommandsWritten()); 1824 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1825 EXPECT_EQ(0, results[0]); 1826 EXPECT_EQ(kSentinel, results[num_results]); 1827 // try bad enum results. 1828 ClearCommands(); 1829 results[2] = 0; 1830 pnames[1] = GL_TRUE; 1831 gl_->GetMultipleIntegervCHROMIUM( 1832 &pnames[0], kNumPnames, &results[0], kResultsSize); 1833 EXPECT_TRUE(NoCommandsWritten()); 1834 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError()); 1835 EXPECT_EQ(0, results[0]); 1836 EXPECT_EQ(kSentinel, results[num_results]); 1837 } 1838 1839 TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMGoodArgs) { 1840 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 1841 const GLuint kProgramId = 123; 1842 const char kBad = 0x12; 1843 GLsizei size = 0; 1844 const Str7 kString = {"foobar"}; 1845 char buf[20]; 1846 1847 ExpectedMemoryInfo mem1 = 1848 GetExpectedMemory(MaxTransferBufferSize()); 1849 ExpectedMemoryInfo result1 = 1850 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 1851 ExpectedMemoryInfo result2 = 1852 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1853 1854 memset(buf, kBad, sizeof(buf)); 1855 EXPECT_CALL(*command_buffer(), OnFlush()) 1856 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 1857 SetMemory(mem1.ptr, kString))) 1858 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1859 .RetiresOnSaturation(); 1860 1861 struct Cmds { 1862 cmd::SetBucketSize set_bucket_size1; 1863 cmds::GetProgramInfoCHROMIUM get_program_info; 1864 cmd::GetBucketStart get_bucket_start; 1865 cmd::SetToken set_token1; 1866 cmd::SetBucketSize set_bucket_size2; 1867 }; 1868 Cmds expected; 1869 expected.set_bucket_size1.Init(kBucketId, 0); 1870 expected.get_program_info.Init(kProgramId, kBucketId); 1871 expected.get_bucket_start.Init( 1872 kBucketId, result1.id, result1.offset, 1873 MaxTransferBufferSize(), mem1.id, mem1.offset); 1874 expected.set_token1.Init(GetNextToken()); 1875 expected.set_bucket_size2.Init(kBucketId, 0); 1876 gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), &size, &buf); 1877 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1878 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 1879 EXPECT_EQ(sizeof(kString), static_cast<size_t>(size)); 1880 EXPECT_STREQ(kString.str, buf); 1881 EXPECT_EQ(buf[sizeof(kString)], kBad); 1882 } 1883 1884 TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) { 1885 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 1886 const GLuint kProgramId = 123; 1887 GLsizei size = 0; 1888 const Str7 kString = {"foobar"}; 1889 char buf[20]; 1890 1891 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 1892 ExpectedMemoryInfo result1 = 1893 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 1894 ExpectedMemoryInfo result2 = 1895 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1896 ExpectedMemoryInfo result3 = 1897 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1898 ExpectedMemoryInfo result4 = 1899 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1900 1901 EXPECT_CALL(*command_buffer(), OnFlush()) 1902 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 1903 SetMemory(mem1.ptr, kString))) 1904 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1905 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 1906 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 1907 .RetiresOnSaturation(); 1908 1909 // try bufsize not big enough. 1910 struct Cmds { 1911 cmd::SetBucketSize set_bucket_size1; 1912 cmds::GetProgramInfoCHROMIUM get_program_info; 1913 cmd::GetBucketStart get_bucket_start; 1914 cmd::SetToken set_token1; 1915 cmd::SetBucketSize set_bucket_size2; 1916 }; 1917 Cmds expected; 1918 expected.set_bucket_size1.Init(kBucketId, 0); 1919 expected.get_program_info.Init(kProgramId, kBucketId); 1920 expected.get_bucket_start.Init( 1921 kBucketId, result1.id, result1.offset, 1922 MaxTransferBufferSize(), mem1.id, mem1.offset); 1923 expected.set_token1.Init(GetNextToken()); 1924 expected.set_bucket_size2.Init(kBucketId, 0); 1925 gl_->GetProgramInfoCHROMIUM(kProgramId, 6, &size, &buf); 1926 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1927 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError()); 1928 ClearCommands(); 1929 1930 // try bad bufsize 1931 gl_->GetProgramInfoCHROMIUM(kProgramId, -1, &size, &buf); 1932 EXPECT_TRUE(NoCommandsWritten()); 1933 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1934 ClearCommands(); 1935 // try no size ptr. 1936 gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), NULL, &buf); 1937 EXPECT_TRUE(NoCommandsWritten()); 1938 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1939 } 1940 1941 // Test that things are cached 1942 TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) { 1943 struct PNameValue { 1944 GLenum pname; 1945 GLint expected; 1946 }; 1947 const PNameValue pairs[] = { 1948 { GL_ACTIVE_TEXTURE, GL_TEXTURE0, }, 1949 { GL_TEXTURE_BINDING_2D, 0, }, 1950 { GL_TEXTURE_BINDING_CUBE_MAP, 0, }, 1951 { GL_FRAMEBUFFER_BINDING, 0, }, 1952 { GL_RENDERBUFFER_BINDING, 0, }, 1953 { GL_ARRAY_BUFFER_BINDING, 0, }, 1954 { GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, }, 1955 { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kMaxCombinedTextureImageUnits, }, 1956 { GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMaxCubeMapTextureSize, }, 1957 { GL_MAX_FRAGMENT_UNIFORM_VECTORS, kMaxFragmentUniformVectors, }, 1958 { GL_MAX_RENDERBUFFER_SIZE, kMaxRenderbufferSize, }, 1959 { GL_MAX_TEXTURE_IMAGE_UNITS, kMaxTextureImageUnits, }, 1960 { GL_MAX_TEXTURE_SIZE, kMaxTextureSize, }, 1961 { GL_MAX_VARYING_VECTORS, kMaxVaryingVectors, }, 1962 { GL_MAX_VERTEX_ATTRIBS, kMaxVertexAttribs, }, 1963 { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMaxVertexTextureImageUnits, }, 1964 { GL_MAX_VERTEX_UNIFORM_VECTORS, kMaxVertexUniformVectors, }, 1965 { GL_NUM_COMPRESSED_TEXTURE_FORMATS, kNumCompressedTextureFormats, }, 1966 { GL_NUM_SHADER_BINARY_FORMATS, kNumShaderBinaryFormats, }, 1967 }; 1968 size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); 1969 for (size_t ii = 0; ii < num_pairs; ++ii) { 1970 const PNameValue& pv = pairs[ii]; 1971 GLint v = -1; 1972 gl_->GetIntegerv(pv.pname, &v); 1973 EXPECT_TRUE(NoCommandsWritten()); 1974 EXPECT_EQ(pv.expected, v); 1975 } 1976 1977 ExpectedMemoryInfo result1 = 1978 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1979 1980 EXPECT_CALL(*command_buffer(), OnFlush()) 1981 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1982 .RetiresOnSaturation(); 1983 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 1984 } 1985 1986 TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) { 1987 struct PNameValue { 1988 GLenum pname; 1989 GLint expected; 1990 }; 1991 gl_->ActiveTexture(GL_TEXTURE4); 1992 gl_->BindBuffer(GL_ARRAY_BUFFER, 2); 1993 gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 3); 1994 gl_->BindFramebuffer(GL_FRAMEBUFFER, 4); 1995 gl_->BindRenderbuffer(GL_RENDERBUFFER, 5); 1996 gl_->BindTexture(GL_TEXTURE_2D, 6); 1997 gl_->BindTexture(GL_TEXTURE_CUBE_MAP, 7); 1998 1999 const PNameValue pairs[] = { 2000 { GL_ACTIVE_TEXTURE, GL_TEXTURE4, }, 2001 { GL_ARRAY_BUFFER_BINDING, 2, }, 2002 { GL_ELEMENT_ARRAY_BUFFER_BINDING, 3, }, 2003 { GL_FRAMEBUFFER_BINDING, 4, }, 2004 { GL_RENDERBUFFER_BINDING, 5, }, 2005 { GL_TEXTURE_BINDING_2D, 6, }, 2006 { GL_TEXTURE_BINDING_CUBE_MAP, 7, }, 2007 }; 2008 size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); 2009 for (size_t ii = 0; ii < num_pairs; ++ii) { 2010 const PNameValue& pv = pairs[ii]; 2011 GLint v = -1; 2012 gl_->GetIntegerv(pv.pname, &v); 2013 EXPECT_EQ(pv.expected, v); 2014 } 2015 2016 ExpectedMemoryInfo result1 = 2017 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2018 2019 EXPECT_CALL(*command_buffer(), OnFlush()) 2020 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 2021 .RetiresOnSaturation(); 2022 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 2023 } 2024 2025 static bool CheckRect( 2026 int width, int height, GLenum format, GLenum type, int alignment, 2027 bool flip_y, const uint8* r1, const uint8* r2) { 2028 uint32 size = 0; 2029 uint32 unpadded_row_size = 0; 2030 uint32 padded_row_size = 0; 2031 if (!GLES2Util::ComputeImageDataSizes( 2032 width, height, format, type, alignment, &size, &unpadded_row_size, 2033 &padded_row_size)) { 2034 return false; 2035 } 2036 2037 int r2_stride = flip_y ? 2038 -static_cast<int>(padded_row_size) : 2039 static_cast<int>(padded_row_size); 2040 r2 = flip_y ? (r2 + (height - 1) * padded_row_size) : r2; 2041 2042 for (int y = 0; y < height; ++y) { 2043 if (memcmp(r1, r2, unpadded_row_size) != 0) { 2044 return false; 2045 } 2046 r1 += padded_row_size; 2047 r2 += r2_stride; 2048 } 2049 return true; 2050 } 2051 2052 ACTION_P8(CheckRectAction, width, height, format, type, alignment, flip_y, 2053 r1, r2) { 2054 EXPECT_TRUE(CheckRect( 2055 width, height, format, type, alignment, flip_y, r1, r2)); 2056 } 2057 2058 // Test TexImage2D with and without flip_y 2059 TEST_F(GLES2ImplementationTest, TexImage2D) { 2060 struct Cmds { 2061 cmds::TexImage2D tex_image_2d; 2062 cmd::SetToken set_token; 2063 }; 2064 struct Cmds2 { 2065 cmds::TexImage2D tex_image_2d; 2066 cmd::SetToken set_token; 2067 }; 2068 const GLenum kTarget = GL_TEXTURE_2D; 2069 const GLint kLevel = 0; 2070 const GLenum kFormat = GL_RGB; 2071 const GLsizei kWidth = 3; 2072 const GLsizei kHeight = 4; 2073 const GLint kBorder = 0; 2074 const GLenum kType = GL_UNSIGNED_BYTE; 2075 const GLint kPixelStoreUnpackAlignment = 4; 2076 static uint8 pixels[] = { 2077 11, 12, 13, 13, 14, 15, 15, 16, 17, 101, 102, 103, 2078 21, 22, 23, 23, 24, 25, 25, 26, 27, 201, 202, 203, 2079 31, 32, 33, 33, 34, 35, 35, 36, 37, 123, 124, 125, 2080 41, 42, 43, 43, 44, 45, 45, 46, 47, 2081 }; 2082 2083 ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels)); 2084 2085 Cmds expected; 2086 expected.tex_image_2d.Init( 2087 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2088 mem1.id, mem1.offset); 2089 expected.set_token.Init(GetNextToken()); 2090 gl_->TexImage2D( 2091 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2092 pixels); 2093 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2094 EXPECT_TRUE(CheckRect( 2095 kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false, 2096 pixels, mem1.ptr)); 2097 2098 ClearCommands(); 2099 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2100 2101 ExpectedMemoryInfo mem2 = GetExpectedMemory(sizeof(pixels)); 2102 Cmds2 expected2; 2103 expected2.tex_image_2d.Init( 2104 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2105 mem2.id, mem2.offset); 2106 expected2.set_token.Init(GetNextToken()); 2107 const void* commands2 = GetPut(); 2108 gl_->TexImage2D( 2109 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2110 pixels); 2111 EXPECT_EQ(0, memcmp(&expected2, commands2, sizeof(expected2))); 2112 EXPECT_TRUE(CheckRect( 2113 kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, true, 2114 pixels, mem2.ptr)); 2115 } 2116 2117 // Test TexImage2D with 2 writes 2118 TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { 2119 struct Cmds { 2120 cmds::TexImage2D tex_image_2d; 2121 cmds::TexSubImage2D tex_sub_image_2d1; 2122 cmd::SetToken set_token1; 2123 cmds::TexSubImage2D tex_sub_image_2d2; 2124 cmd::SetToken set_token2; 2125 }; 2126 const GLenum kTarget = GL_TEXTURE_2D; 2127 const GLint kLevel = 0; 2128 const GLenum kFormat = GL_RGB; 2129 const GLint kBorder = 0; 2130 const GLenum kType = GL_UNSIGNED_BYTE; 2131 const GLint kPixelStoreUnpackAlignment = 4; 2132 const GLsizei kWidth = 3; 2133 2134 uint32 size = 0; 2135 uint32 unpadded_row_size = 0; 2136 uint32 padded_row_size = 0; 2137 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2138 kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, 2139 &size, &unpadded_row_size, &padded_row_size)); 2140 const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2; 2141 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2142 kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, 2143 &size, NULL, NULL)); 2144 uint32 half_size = 0; 2145 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2146 kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, 2147 &half_size, NULL, NULL)); 2148 2149 scoped_ptr<uint8[]> pixels(new uint8[size]); 2150 for (uint32 ii = 0; ii < size; ++ii) { 2151 pixels[ii] = static_cast<uint8>(ii); 2152 } 2153 2154 ExpectedMemoryInfo mem1 = GetExpectedMemory(half_size); 2155 ExpectedMemoryInfo mem2 = GetExpectedMemory(half_size); 2156 2157 Cmds expected; 2158 expected.tex_image_2d.Init( 2159 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2160 0, 0); 2161 expected.tex_sub_image_2d1.Init( 2162 kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, 2163 mem1.id, mem1.offset, true); 2164 expected.set_token1.Init(GetNextToken()); 2165 expected.tex_sub_image_2d2.Init( 2166 kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, 2167 mem2.id, mem2.offset, true); 2168 expected.set_token2.Init(GetNextToken()); 2169 2170 // TODO(gman): Make it possible to run this test 2171 // EXPECT_CALL(*command_buffer(), OnFlush()) 2172 // .WillOnce(CheckRectAction( 2173 // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, 2174 // false, pixels.get(), 2175 // GetExpectedTransferAddressFromOffsetAs<uint8>(offset1, half_size))) 2176 // .RetiresOnSaturation(); 2177 2178 gl_->TexImage2D( 2179 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2180 pixels.get()); 2181 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2182 EXPECT_TRUE(CheckRect( 2183 kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, false, 2184 pixels.get() + kHeight / 2 * padded_row_size, mem2.ptr)); 2185 2186 ClearCommands(); 2187 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2188 const void* commands2 = GetPut(); 2189 ExpectedMemoryInfo mem3 = GetExpectedMemory(half_size); 2190 ExpectedMemoryInfo mem4 = GetExpectedMemory(half_size); 2191 expected.tex_image_2d.Init( 2192 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2193 0, 0); 2194 expected.tex_sub_image_2d1.Init( 2195 kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, 2196 mem3.id, mem3.offset, true); 2197 expected.set_token1.Init(GetNextToken()); 2198 expected.tex_sub_image_2d2.Init( 2199 kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, 2200 mem4.id, mem4.offset, true); 2201 expected.set_token2.Init(GetNextToken()); 2202 2203 // TODO(gman): Make it possible to run this test 2204 // EXPECT_CALL(*command_buffer(), OnFlush()) 2205 // .WillOnce(CheckRectAction( 2206 // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, 2207 // true, pixels.get(), 2208 // GetExpectedTransferAddressFromOffsetAs<uint8>(offset3, half_size))) 2209 // .RetiresOnSaturation(); 2210 2211 gl_->TexImage2D( 2212 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2213 pixels.get()); 2214 EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected))); 2215 EXPECT_TRUE(CheckRect( 2216 kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, true, 2217 pixels.get() + kHeight / 2 * padded_row_size, mem4.ptr)); 2218 } 2219 2220 // Test TexSubImage2D with GL_PACK_FLIP_Y set and partial multirow transfers 2221 TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) { 2222 const GLsizei kTextureWidth = MaxTransferBufferSize() / 4; 2223 const GLsizei kTextureHeight = 7; 2224 const GLsizei kSubImageWidth = MaxTransferBufferSize() / 8; 2225 const GLsizei kSubImageHeight = 4; 2226 const GLint kSubImageXOffset = 1; 2227 const GLint kSubImageYOffset = 2; 2228 const GLenum kFormat = GL_RGBA; 2229 const GLenum kType = GL_UNSIGNED_BYTE; 2230 const GLenum kTarget = GL_TEXTURE_2D; 2231 const GLint kLevel = 0; 2232 const GLint kBorder = 0; 2233 const GLint kPixelStoreUnpackAlignment = 4; 2234 2235 struct Cmds { 2236 cmds::PixelStorei pixel_store_i1; 2237 cmds::TexImage2D tex_image_2d; 2238 cmds::PixelStorei pixel_store_i2; 2239 cmds::TexSubImage2D tex_sub_image_2d1; 2240 cmd::SetToken set_token1; 2241 cmds::TexSubImage2D tex_sub_image_2d2; 2242 cmd::SetToken set_token2; 2243 }; 2244 2245 uint32 sub_2_high_size = 0; 2246 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2247 kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, 2248 &sub_2_high_size, NULL, NULL)); 2249 2250 ExpectedMemoryInfo mem1 = GetExpectedMemory(sub_2_high_size); 2251 ExpectedMemoryInfo mem2 = GetExpectedMemory(sub_2_high_size); 2252 2253 Cmds expected; 2254 expected.pixel_store_i1.Init(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment); 2255 expected.tex_image_2d.Init( 2256 kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat, 2257 kType, 0, 0); 2258 expected.pixel_store_i2.Init(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2259 expected.tex_sub_image_2d1.Init(kTarget, kLevel, kSubImageXOffset, 2260 kSubImageYOffset + 2, kSubImageWidth, 2, kFormat, kType, 2261 mem1.id, mem1.offset, false); 2262 expected.set_token1.Init(GetNextToken()); 2263 expected.tex_sub_image_2d2.Init(kTarget, kLevel, kSubImageXOffset, 2264 kSubImageYOffset, kSubImageWidth , 2, kFormat, kType, 2265 mem2.id, mem2.offset, false); 2266 expected.set_token2.Init(GetNextToken()); 2267 2268 gl_->PixelStorei(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment); 2269 gl_->TexImage2D( 2270 kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat, 2271 kType, NULL); 2272 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2273 scoped_ptr<uint32[]> pixels(new uint32[kSubImageWidth * kSubImageHeight]); 2274 for (int y = 0; y < kSubImageHeight; ++y) { 2275 for (int x = 0; x < kSubImageWidth; ++x) { 2276 pixels.get()[kSubImageWidth * y + x] = x | (y << 16); 2277 } 2278 } 2279 gl_->TexSubImage2D( 2280 GL_TEXTURE_2D, 0, kSubImageXOffset, kSubImageYOffset, kSubImageWidth, 2281 kSubImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); 2282 2283 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2284 EXPECT_TRUE(CheckRect( 2285 kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, true, 2286 reinterpret_cast<uint8*>(pixels.get() + 2 * kSubImageWidth), 2287 mem2.ptr)); 2288 } 2289 2290 TEST_F(GLES2ImplementationTest, SubImageUnpack) { 2291 static const GLint unpack_alignments[] = { 1, 2, 4, 8 }; 2292 2293 static const GLenum kFormat = GL_RGB; 2294 static const GLenum kType = GL_UNSIGNED_BYTE; 2295 static const GLint kLevel = 0; 2296 static const GLint kBorder = 0; 2297 // We're testing using the unpack params to pull a subimage out of a larger 2298 // source of pixels. Here we specify the subimage by its border rows / 2299 // columns. 2300 static const GLint kSrcWidth = 33; 2301 static const GLint kSrcSubImageX0 = 11; 2302 static const GLint kSrcSubImageX1 = 20; 2303 static const GLint kSrcSubImageY0 = 18; 2304 static const GLint kSrcSubImageY1 = 23; 2305 static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0; 2306 static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0; 2307 2308 // these are only used in the texsubimage tests 2309 static const GLint kTexWidth = 1023; 2310 static const GLint kTexHeight = 511; 2311 static const GLint kTexSubXOffset = 419; 2312 static const GLint kTexSubYOffset = 103; 2313 2314 struct { 2315 cmds::PixelStorei pixel_store_i; 2316 cmds::PixelStorei pixel_store_i2; 2317 cmds::TexImage2D tex_image_2d; 2318 } texImageExpected; 2319 2320 struct { 2321 cmds::PixelStorei pixel_store_i; 2322 cmds::PixelStorei pixel_store_i2; 2323 cmds::TexImage2D tex_image_2d; 2324 cmds::TexSubImage2D tex_sub_image_2d; 2325 } texSubImageExpected; 2326 2327 uint32 src_size; 2328 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2329 kSrcWidth, kSrcSubImageY1, kFormat, kType, 8, &src_size, NULL, NULL)); 2330 scoped_ptr<uint8[]> src_pixels; 2331 src_pixels.reset(new uint8[src_size]); 2332 for (size_t i = 0; i < src_size; ++i) { 2333 src_pixels[i] = static_cast<int8>(i); 2334 } 2335 2336 for (int sub = 0; sub < 2; ++sub) { 2337 for (int flip_y = 0; flip_y < 2; ++flip_y) { 2338 for (size_t a = 0; a < arraysize(unpack_alignments); ++a) { 2339 GLint alignment = unpack_alignments[a]; 2340 uint32 size; 2341 uint32 unpadded_row_size; 2342 uint32 padded_row_size; 2343 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2344 kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, alignment, 2345 &size, &unpadded_row_size, &padded_row_size)); 2346 ASSERT_TRUE(size <= MaxTransferBufferSize()); 2347 ExpectedMemoryInfo mem = GetExpectedMemory(size); 2348 2349 const void* commands = GetPut(); 2350 gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment); 2351 gl_->PixelStorei(GL_UNPACK_ROW_LENGTH, kSrcWidth); 2352 gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS, kSrcSubImageX0); 2353 gl_->PixelStorei(GL_UNPACK_SKIP_ROWS, kSrcSubImageY0); 2354 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); 2355 if (sub) { 2356 gl_->TexImage2D( 2357 GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, 2358 kFormat, kType, NULL); 2359 gl_->TexSubImage2D( 2360 GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, 2361 kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, 2362 src_pixels.get()); 2363 texSubImageExpected.pixel_store_i.Init( 2364 GL_UNPACK_ALIGNMENT, alignment); 2365 texSubImageExpected.pixel_store_i2.Init( 2366 GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); 2367 texSubImageExpected.tex_image_2d.Init( 2368 GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, 2369 kFormat, kType, 0, 0); 2370 texSubImageExpected.tex_sub_image_2d.Init( 2371 GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, 2372 kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id, 2373 mem.offset, GL_FALSE); 2374 EXPECT_EQ(0, memcmp( 2375 &texSubImageExpected, commands, sizeof(texSubImageExpected))); 2376 } else { 2377 gl_->TexImage2D( 2378 GL_TEXTURE_2D, kLevel, kFormat, 2379 kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType, 2380 src_pixels.get()); 2381 texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment); 2382 texImageExpected.pixel_store_i2.Init( 2383 GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); 2384 texImageExpected.tex_image_2d.Init( 2385 GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth, 2386 kSrcSubImageHeight, kBorder, kFormat, kType, mem.id, mem.offset); 2387 EXPECT_EQ(0, memcmp( 2388 &texImageExpected, commands, sizeof(texImageExpected))); 2389 } 2390 uint32 src_padded_row_size; 2391 ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize( 2392 kSrcWidth, kFormat, kType, alignment, &src_padded_row_size)); 2393 uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize( 2394 kFormat, kType); 2395 for (int y = 0; y < kSrcSubImageHeight; ++y) { 2396 GLint src_sub_y = flip_y ? kSrcSubImageHeight - y - 1 : y; 2397 const uint8* src_row = src_pixels.get() + 2398 (kSrcSubImageY0 + src_sub_y) * src_padded_row_size + 2399 bytes_per_group * kSrcSubImageX0; 2400 const uint8* dst_row = mem.ptr + y * padded_row_size; 2401 EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size)); 2402 } 2403 ClearCommands(); 2404 } 2405 } 2406 } 2407 } 2408 2409 // Binds can not be cached with bind_generates_resource = false because 2410 // our id might not be valid. More specifically if you bind on contextA then 2411 // delete on contextB the resource is still bound on contextA but GetInterger 2412 // won't return an id. 2413 TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) { 2414 struct PNameValue { 2415 GLenum pname; 2416 GLint expected; 2417 }; 2418 const PNameValue pairs[] = { 2419 { GL_TEXTURE_BINDING_2D, 1, }, 2420 { GL_TEXTURE_BINDING_CUBE_MAP, 2, }, 2421 { GL_FRAMEBUFFER_BINDING, 3, }, 2422 { GL_RENDERBUFFER_BINDING, 4, }, 2423 { GL_ARRAY_BUFFER_BINDING, 5, }, 2424 { GL_ELEMENT_ARRAY_BUFFER_BINDING, 6, }, 2425 }; 2426 size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); 2427 for (size_t ii = 0; ii < num_pairs; ++ii) { 2428 const PNameValue& pv = pairs[ii]; 2429 GLint v = -1; 2430 ExpectedMemoryInfo result1 = 2431 GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result)); 2432 EXPECT_CALL(*command_buffer(), OnFlush()) 2433 .WillOnce(SetMemory(result1.ptr, 2434 SizedResultHelper<GLuint>(pv.expected))) 2435 .RetiresOnSaturation(); 2436 gl_->GetIntegerv(pv.pname, &v); 2437 EXPECT_EQ(pv.expected, v); 2438 } 2439 } 2440 2441 TEST_F(GLES2ImplementationTest, CreateStreamTextureCHROMIUM) { 2442 const GLuint kTextureId = 123; 2443 const GLuint kResult = 456; 2444 2445 struct Cmds { 2446 cmds::CreateStreamTextureCHROMIUM create_stream; 2447 }; 2448 2449 ExpectedMemoryInfo result1 = 2450 GetExpectedResultMemory( 2451 sizeof(cmds::CreateStreamTextureCHROMIUM::Result)); 2452 ExpectedMemoryInfo result2 = 2453 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2454 2455 Cmds expected; 2456 expected.create_stream.Init(kTextureId, result1.id, result1.offset); 2457 2458 EXPECT_CALL(*command_buffer(), OnFlush()) 2459 .WillOnce(SetMemory(result1.ptr, kResult)) 2460 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 2461 .RetiresOnSaturation(); 2462 2463 GLuint handle = gl_->CreateStreamTextureCHROMIUM(kTextureId); 2464 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2465 EXPECT_EQ(handle, kResult); 2466 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 2467 } 2468 2469 TEST_F(GLES2ImplementationTest, GetString) { 2470 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 2471 const Str7 kString = {"foobar"}; 2472 // GL_CHROMIUM_map_sub GL_CHROMIUM_flipy are hard coded into 2473 // GLES2Implementation. 2474 const char* expected_str = 2475 "foobar " 2476 "GL_CHROMIUM_flipy " 2477 "GL_CHROMIUM_map_sub " 2478 "GL_CHROMIUM_shallow_flush " 2479 "GL_EXT_unpack_subimage"; 2480 const char kBad = 0x12; 2481 struct Cmds { 2482 cmd::SetBucketSize set_bucket_size1; 2483 cmds::GetString get_string; 2484 cmd::GetBucketStart get_bucket_start; 2485 cmd::SetToken set_token1; 2486 cmd::SetBucketSize set_bucket_size2; 2487 }; 2488 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 2489 ExpectedMemoryInfo result1 = 2490 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 2491 Cmds expected; 2492 expected.set_bucket_size1.Init(kBucketId, 0); 2493 expected.get_string.Init(GL_EXTENSIONS, kBucketId); 2494 expected.get_bucket_start.Init( 2495 kBucketId, result1.id, result1.offset, 2496 MaxTransferBufferSize(), mem1.id, mem1.offset); 2497 expected.set_token1.Init(GetNextToken()); 2498 expected.set_bucket_size2.Init(kBucketId, 0); 2499 char buf[sizeof(kString) + 1]; 2500 memset(buf, kBad, sizeof(buf)); 2501 2502 EXPECT_CALL(*command_buffer(), OnFlush()) 2503 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 2504 SetMemory(mem1.ptr, kString))) 2505 .RetiresOnSaturation(); 2506 2507 const GLubyte* result = gl_->GetString(GL_EXTENSIONS); 2508 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2509 EXPECT_STREQ(expected_str, reinterpret_cast<const char*>(result)); 2510 } 2511 2512 TEST_F(GLES2ImplementationTest, PixelStoreiGLPackReverseRowOrderANGLE) { 2513 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 2514 const Str7 kString = {"foobar"}; 2515 struct Cmds { 2516 cmd::SetBucketSize set_bucket_size1; 2517 cmds::GetString get_string; 2518 cmd::GetBucketStart get_bucket_start; 2519 cmd::SetToken set_token1; 2520 cmd::SetBucketSize set_bucket_size2; 2521 cmds::PixelStorei pixel_store; 2522 }; 2523 2524 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 2525 ExpectedMemoryInfo result1 = 2526 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 2527 2528 Cmds expected; 2529 expected.set_bucket_size1.Init(kBucketId, 0); 2530 expected.get_string.Init(GL_EXTENSIONS, kBucketId); 2531 expected.get_bucket_start.Init( 2532 kBucketId, result1.id, result1.offset, 2533 MaxTransferBufferSize(), mem1.id, mem1.offset); 2534 expected.set_token1.Init(GetNextToken()); 2535 expected.set_bucket_size2.Init(kBucketId, 0); 2536 expected.pixel_store.Init(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1); 2537 2538 EXPECT_CALL(*command_buffer(), OnFlush()) 2539 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 2540 SetMemory(mem1.ptr, kString))) 2541 .RetiresOnSaturation(); 2542 2543 gl_->PixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1); 2544 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2545 } 2546 2547 TEST_F(GLES2ImplementationTest, CreateProgram) { 2548 struct Cmds { 2549 cmds::CreateProgram cmd; 2550 }; 2551 2552 Cmds expected; 2553 expected.cmd.Init(kProgramsAndShadersStartId); 2554 GLuint id = gl_->CreateProgram(); 2555 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2556 EXPECT_EQ(kProgramsAndShadersStartId, id); 2557 } 2558 2559 TEST_F(GLES2ImplementationTest, BufferDataLargerThanTransferBuffer) { 2560 struct Cmds { 2561 cmds::BufferData set_size; 2562 cmds::BufferSubData copy_data1; 2563 cmd::SetToken set_token1; 2564 cmds::BufferSubData copy_data2; 2565 cmd::SetToken set_token2; 2566 }; 2567 const unsigned kUsableSize = 2568 kTransferBufferSize - GLES2Implementation::kStartingOffset; 2569 uint8 buf[kUsableSize * 2] = { 0, }; 2570 2571 ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize); 2572 ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize); 2573 2574 Cmds expected; 2575 expected.set_size.Init( 2576 GL_ARRAY_BUFFER, arraysize(buf), 0, 0, GL_DYNAMIC_DRAW); 2577 expected.copy_data1.Init( 2578 GL_ARRAY_BUFFER, 0, kUsableSize, mem1.id, mem1.offset); 2579 expected.set_token1.Init(GetNextToken()); 2580 expected.copy_data2.Init( 2581 GL_ARRAY_BUFFER, kUsableSize, kUsableSize, mem2.id, mem2.offset); 2582 expected.set_token2.Init(GetNextToken()); 2583 gl_->BufferData(GL_ARRAY_BUFFER, arraysize(buf), buf, GL_DYNAMIC_DRAW); 2584 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2585 } 2586 2587 TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) { 2588 static const GLenum kStates[] = { 2589 GL_DITHER, 2590 GL_BLEND, 2591 GL_CULL_FACE, 2592 GL_DEPTH_TEST, 2593 GL_POLYGON_OFFSET_FILL, 2594 GL_SAMPLE_ALPHA_TO_COVERAGE, 2595 GL_SAMPLE_COVERAGE, 2596 GL_SCISSOR_TEST, 2597 GL_STENCIL_TEST, 2598 }; 2599 struct Cmds { 2600 cmds::Enable enable_cmd; 2601 }; 2602 Cmds expected; 2603 2604 for (size_t ii = 0; ii < arraysize(kStates); ++ii) { 2605 GLenum state = kStates[ii]; 2606 expected.enable_cmd.Init(state); 2607 GLboolean result = gl_->IsEnabled(state); 2608 EXPECT_EQ(static_cast<GLboolean>(ii == 0), result); 2609 EXPECT_TRUE(NoCommandsWritten()); 2610 const void* commands = GetPut(); 2611 if (!result) { 2612 gl_->Enable(state); 2613 EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected))); 2614 } 2615 ClearCommands(); 2616 result = gl_->IsEnabled(state); 2617 EXPECT_TRUE(result); 2618 EXPECT_TRUE(NoCommandsWritten()); 2619 } 2620 } 2621 2622 TEST_F(GLES2ImplementationTest, BindVertexArrayOES) { 2623 GLuint id = 0; 2624 gl_->GenVertexArraysOES(1, &id); 2625 ClearCommands(); 2626 2627 struct Cmds { 2628 cmds::BindVertexArrayOES cmd; 2629 }; 2630 Cmds expected; 2631 expected.cmd.Init(id); 2632 2633 const void* commands = GetPut(); 2634 gl_->BindVertexArrayOES(id); 2635 EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected))); 2636 ClearCommands(); 2637 gl_->BindVertexArrayOES(id); 2638 EXPECT_TRUE(NoCommandsWritten()); 2639 } 2640 2641 TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) { 2642 // Test GetQueryivEXT returns 0 if no current query. 2643 GLint param = -1; 2644 gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, ¶m); 2645 EXPECT_EQ(0, param); 2646 2647 GLuint expected_ids[2] = { 1, 2 }; // These must match what's actually genned. 2648 struct GenCmds { 2649 cmds::GenQueriesEXTImmediate gen; 2650 GLuint data[2]; 2651 }; 2652 GenCmds expected_gen_cmds; 2653 expected_gen_cmds.gen.Init(arraysize(expected_ids), &expected_ids[0]); 2654 GLuint ids[arraysize(expected_ids)] = { 0, }; 2655 gl_->GenQueriesEXT(arraysize(expected_ids), &ids[0]); 2656 EXPECT_EQ(0, memcmp( 2657 &expected_gen_cmds, commands_, sizeof(expected_gen_cmds))); 2658 GLuint id1 = ids[0]; 2659 GLuint id2 = ids[1]; 2660 ClearCommands(); 2661 2662 // Test BeginQueryEXT fails if id = 0. 2663 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0); 2664 EXPECT_TRUE(NoCommandsWritten()); 2665 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2666 2667 // Test BeginQueryEXT fails if id not GENed. 2668 // TODO(gman): 2669 2670 // Test BeginQueryEXT inserts command. 2671 struct BeginCmds { 2672 cmds::BeginQueryEXT begin_query; 2673 }; 2674 BeginCmds expected_begin_cmds; 2675 const void* commands = GetPut(); 2676 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1); 2677 QueryTracker::Query* query = GetQuery(id1); 2678 ASSERT_TRUE(query != NULL); 2679 expected_begin_cmds.begin_query.Init( 2680 GL_ANY_SAMPLES_PASSED_EXT, id1, query->shm_id(), query->shm_offset()); 2681 EXPECT_EQ(0, memcmp( 2682 &expected_begin_cmds, commands, sizeof(expected_begin_cmds))); 2683 ClearCommands(); 2684 2685 // Test GetQueryivEXT returns id. 2686 param = -1; 2687 gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, ¶m); 2688 EXPECT_EQ(id1, static_cast<GLuint>(param)); 2689 gl_->GetQueryivEXT( 2690 GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_CURRENT_QUERY_EXT, ¶m); 2691 EXPECT_EQ(0, param); 2692 2693 // Test BeginQueryEXT fails if between Begin/End. 2694 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id2); 2695 EXPECT_TRUE(NoCommandsWritten()); 2696 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2697 2698 // Test EndQueryEXT fails if target not same as current query. 2699 ClearCommands(); 2700 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); 2701 EXPECT_TRUE(NoCommandsWritten()); 2702 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2703 2704 // Test EndQueryEXT sends command 2705 struct EndCmds { 2706 cmds::EndQueryEXT end_query; 2707 }; 2708 EndCmds expected_end_cmds; 2709 expected_end_cmds.end_query.Init( 2710 GL_ANY_SAMPLES_PASSED_EXT, query->submit_count()); 2711 commands = GetPut(); 2712 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 2713 EXPECT_EQ(0, memcmp( 2714 &expected_end_cmds, commands, sizeof(expected_end_cmds))); 2715 2716 // Test EndQueryEXT fails if no current query. 2717 ClearCommands(); 2718 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 2719 EXPECT_TRUE(NoCommandsWritten()); 2720 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2721 2722 // Test 2nd Begin/End increments count. 2723 uint32 old_submit_count = query->submit_count(); 2724 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1); 2725 EXPECT_NE(old_submit_count, query->submit_count()); 2726 expected_end_cmds.end_query.Init( 2727 GL_ANY_SAMPLES_PASSED_EXT, query->submit_count()); 2728 commands = GetPut(); 2729 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 2730 EXPECT_EQ(0, memcmp( 2731 &expected_end_cmds, commands, sizeof(expected_end_cmds))); 2732 2733 // Test BeginQueryEXT fails if target changed. 2734 ClearCommands(); 2735 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, id1); 2736 EXPECT_TRUE(NoCommandsWritten()); 2737 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2738 2739 // Test GetQueryObjectuivEXT fails if unused id 2740 GLuint available = 0xBDu; 2741 ClearCommands(); 2742 gl_->GetQueryObjectuivEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2743 EXPECT_TRUE(NoCommandsWritten()); 2744 EXPECT_EQ(0xBDu, available); 2745 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2746 2747 // Test GetQueryObjectuivEXT fails if bad id 2748 ClearCommands(); 2749 gl_->GetQueryObjectuivEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2750 EXPECT_TRUE(NoCommandsWritten()); 2751 EXPECT_EQ(0xBDu, available); 2752 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2753 2754 // Test GetQueryObjectuivEXT CheckResultsAvailable 2755 ClearCommands(); 2756 gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2757 EXPECT_TRUE(NoCommandsWritten()); 2758 EXPECT_EQ(0u, available); 2759 } 2760 2761 TEST_F(GLES2ImplementationTest, ErrorQuery) { 2762 GLuint id = 0; 2763 gl_->GenQueriesEXT(1, &id); 2764 ClearCommands(); 2765 2766 // Test BeginQueryEXT does NOT insert commands. 2767 gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id); 2768 EXPECT_TRUE(NoCommandsWritten()); 2769 QueryTracker::Query* query = GetQuery(id); 2770 ASSERT_TRUE(query != NULL); 2771 2772 // Test EndQueryEXT sends both begin and end command 2773 struct EndCmds { 2774 cmds::BeginQueryEXT begin_query; 2775 cmds::EndQueryEXT end_query; 2776 }; 2777 EndCmds expected_end_cmds; 2778 expected_end_cmds.begin_query.Init( 2779 GL_GET_ERROR_QUERY_CHROMIUM, id, query->shm_id(), query->shm_offset()); 2780 expected_end_cmds.end_query.Init( 2781 GL_GET_ERROR_QUERY_CHROMIUM, query->submit_count()); 2782 const void* commands = GetPut(); 2783 gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); 2784 EXPECT_EQ(0, memcmp( 2785 &expected_end_cmds, commands, sizeof(expected_end_cmds))); 2786 ClearCommands(); 2787 2788 // Check result is not yet available. 2789 GLuint available = 0xBDu; 2790 gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2791 EXPECT_TRUE(NoCommandsWritten()); 2792 EXPECT_EQ(0u, available); 2793 2794 // Test no commands are sent if there is a client side error. 2795 2796 // Generate a client side error 2797 gl_->ActiveTexture(GL_TEXTURE0 - 1); 2798 2799 gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id); 2800 gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); 2801 EXPECT_TRUE(NoCommandsWritten()); 2802 2803 // Check result is available. 2804 gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2805 EXPECT_TRUE(NoCommandsWritten()); 2806 EXPECT_NE(0u, available); 2807 2808 // Check result. 2809 GLuint result = 0xBDu; 2810 gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_EXT, &result); 2811 EXPECT_TRUE(NoCommandsWritten()); 2812 EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), result); 2813 } 2814 2815 #if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 2816 TEST_F(GLES2ImplementationTest, VertexArrays) { 2817 const GLuint kAttribIndex1 = 1; 2818 const GLint kNumComponents1 = 3; 2819 const GLsizei kClientStride = 12; 2820 2821 GLuint id = 0; 2822 gl_->GenVertexArraysOES(1, &id); 2823 ClearCommands(); 2824 2825 gl_->BindVertexArrayOES(id); 2826 2827 // Test that VertexAttribPointer cannot be called with a bound buffer of 0 2828 // unless the offset is NULL 2829 gl_->BindBuffer(GL_ARRAY_BUFFER, 0); 2830 2831 gl_->VertexAttribPointer( 2832 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, 2833 reinterpret_cast<const void*>(4)); 2834 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2835 2836 gl_->VertexAttribPointer( 2837 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, NULL); 2838 EXPECT_EQ(GL_NO_ERROR, CheckError()); 2839 } 2840 #endif 2841 2842 TEST_F(GLES2ImplementationTest, Disable) { 2843 struct Cmds { 2844 cmds::Disable cmd; 2845 }; 2846 Cmds expected; 2847 expected.cmd.Init(GL_DITHER); // Note: DITHER defaults to enabled. 2848 2849 gl_->Disable(GL_DITHER); 2850 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2851 // Check it's cached and not called again. 2852 ClearCommands(); 2853 gl_->Disable(GL_DITHER); 2854 EXPECT_TRUE(NoCommandsWritten()); 2855 } 2856 2857 TEST_F(GLES2ImplementationTest, Enable) { 2858 struct Cmds { 2859 cmds::Enable cmd; 2860 }; 2861 Cmds expected; 2862 expected.cmd.Init(GL_BLEND); // Note: BLEND defaults to disabled. 2863 2864 gl_->Enable(GL_BLEND); 2865 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2866 // Check it's cached and not called again. 2867 ClearCommands(); 2868 gl_->Enable(GL_BLEND); 2869 EXPECT_TRUE(NoCommandsWritten()); 2870 } 2871 2872 2873 #include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h" 2874 2875 } // namespace gles2 2876 } // namespace gpu 2877