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