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