gles2_implementation_unittest.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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 25using testing::_; 26using testing::AtLeast; 27using testing::AnyNumber; 28using testing::DoAll; 29using testing::InSequence; 30using testing::Invoke; 31using testing::Mock; 32using testing::Sequence; 33using testing::StrictMock; 34using testing::Truly; 35using testing::Return; 36 37namespace gpu { 38namespace gles2 { 39 40ACTION_P2(SetMemory, dst, obj) { 41 memcpy(dst, &obj, sizeof(obj)); 42} 43 44ACTION_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. 49template <typename T> 50class 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. 63struct 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. 79struct Str7 { 80 char str[7]; 81}; 82#pragma pack(pop) 83 84class 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 229bool 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 242int MockTransferBuffer::GetShmId() { 243 return buffer_ids_[actual_buffer_index_]; 244} 245 246void* MockTransferBuffer::GetResultBuffer() { 247 return actual_buffer() + actual_buffer_index_ * alignment_; 248} 249 250int MockTransferBuffer::GetResultOffset() { 251 return actual_buffer_index_ * alignment_; 252} 253 254void MockTransferBuffer::Free() { 255 NOTREACHED(); 256} 257 258bool MockTransferBuffer::HaveBuffer() const { 259 return true; 260} 261 262void* 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 284void* 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 292RingBuffer::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 297void MockTransferBuffer::FreePendingToken(void* p, unsigned int /* token */) { 298 EXPECT_EQ(last_alloc_, p); 299 last_alloc_ = NULL; 300} 301 302// API wrapper for Buffers. 303class 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. 317class 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. 331class 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. 345class 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 358class 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()->GetState().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 bool GetBucketContents(uint32 bucket_id, std::vector<int8>* data) { 602 return gl_->GetBucketContents(bucket_id, data); 603 } 604 605 TestContext test_contexts_[kNumTestContexts]; 606 607 scoped_refptr<ShareGroup> share_group_; 608 MockClientGpuControl* gpu_control_; 609 GLES2CmdHelper* helper_; 610 MockTransferBuffer* transfer_buffer_; 611 GLES2Implementation* gl_; 612 CommandBufferEntry* commands_; 613}; 614 615void GLES2ImplementationTest::SetUp() { 616 ContextInitOptions init_options; 617 ASSERT_TRUE(Initialize(init_options)); 618} 619 620void GLES2ImplementationTest::TearDown() { 621 for (int i = 0; i < kNumTestContexts; i++) 622 test_contexts_[i].TearDown(); 623} 624 625class GLES2ImplementationManualInitTest : public GLES2ImplementationTest { 626 protected: 627 virtual void SetUp() OVERRIDE {} 628}; 629 630class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest { 631 protected: 632 virtual void SetUp() OVERRIDE; 633 634 template <class ResApi> 635 void FlushGenerationTest() { 636 GLuint id1, id2, id3; 637 638 // Generate valid id. 639 ResApi::Gen(gl_, 1, &id1); 640 EXPECT_NE(id1, 0u); 641 642 // Delete id1 and generate id2. id1 should not be reused. 643 ResApi::Delete(gl_, 1, &id1); 644 ResApi::Gen(gl_, 1, &id2); 645 EXPECT_NE(id2, 0u); 646 EXPECT_NE(id2, id1); 647 648 // Expect id1 reuse after Flush. 649 gl_->Flush(); 650 ResApi::Gen(gl_, 1, &id3); 651 EXPECT_EQ(id3, id1); 652 } 653 654 // Ids should not be reused unless the |Deleting| context does a Flush() 655 // AND triggers a lazy release after that. 656 template <class ResApi> 657 void CrossContextGenerationTest() { 658 GLES2Implementation* gl1 = test_contexts_[0].gl_.get(); 659 GLES2Implementation* gl2 = test_contexts_[1].gl_.get(); 660 GLuint id1, id2, id3; 661 662 // Delete, no flush on context 1. No reuse. 663 ResApi::Gen(gl1, 1, &id1); 664 ResApi::Delete(gl1, 1, &id1); 665 ResApi::Gen(gl1, 1, &id2); 666 EXPECT_NE(id1, id2); 667 668 // Flush context 2. Still no reuse. 669 gl2->Flush(); 670 ResApi::Gen(gl2, 1, &id3); 671 EXPECT_NE(id1, id3); 672 EXPECT_NE(id2, id3); 673 674 // Flush on context 1, but no lazy release. Still no reuse. 675 gl1->Flush(); 676 ResApi::Gen(gl2, 1, &id3); 677 EXPECT_NE(id1, id3); 678 679 // Lazy release triggered by another Delete. Should reuse id1. 680 ResApi::Delete(gl1, 1, &id2); 681 ResApi::Gen(gl2, 1, &id3); 682 EXPECT_EQ(id1, id3); 683 } 684 685 // Same as CrossContextGenerationTest(), but triggers an Auto Flush on 686 // the Delete(). Tests an edge case regression. 687 template <class ResApi> 688 void CrossContextGenerationAutoFlushTest() { 689 GLES2Implementation* gl1 = test_contexts_[0].gl_.get(); 690 GLES2Implementation* gl2 = test_contexts_[1].gl_.get(); 691 GLuint id1, id2, id3; 692 693 // Delete, no flush on context 1. No reuse. 694 // By half filling the buffer, an internal flush is forced on the Delete(). 695 ResApi::Gen(gl1, 1, &id1); 696 gl1->helper()->Noop(kNumCommandEntries / 2); 697 ResApi::Delete(gl1, 1, &id1); 698 ResApi::Gen(gl1, 1, &id2); 699 EXPECT_NE(id1, id2); 700 701 // Flush context 2. Still no reuse. 702 gl2->Flush(); 703 ResApi::Gen(gl2, 1, &id3); 704 EXPECT_NE(id1, id3); 705 EXPECT_NE(id2, id3); 706 707 // Flush on context 1, but no lazy release. Still no reuse. 708 gl1->Flush(); 709 ResApi::Gen(gl2, 1, &id3); 710 EXPECT_NE(id1, id3); 711 712 // Lazy release triggered by another Delete. Should reuse id1. 713 ResApi::Delete(gl1, 1, &id2); 714 ResApi::Gen(gl2, 1, &id3); 715 EXPECT_EQ(id1, id3); 716 } 717}; 718 719void GLES2ImplementationStrictSharedTest::SetUp() { 720 ContextInitOptions init_options; 721 init_options.bind_generates_resource_client = false; 722 init_options.bind_generates_resource_service = false; 723 ASSERT_TRUE(Initialize(init_options)); 724} 725 726// GCC requires these declarations, but MSVC requires they not be present 727#ifndef _MSC_VER 728const uint8 GLES2ImplementationTest::kInitialValue; 729const int32 GLES2ImplementationTest::kNumCommandEntries; 730const int32 GLES2ImplementationTest::kCommandBufferSizeBytes; 731const size_t GLES2ImplementationTest::kTransferBufferSize; 732const GLint GLES2ImplementationTest::kMaxCombinedTextureImageUnits; 733const GLint GLES2ImplementationTest::kMaxCubeMapTextureSize; 734const GLint GLES2ImplementationTest::kMaxFragmentUniformVectors; 735const GLint GLES2ImplementationTest::kMaxRenderbufferSize; 736const GLint GLES2ImplementationTest::kMaxTextureImageUnits; 737const GLint GLES2ImplementationTest::kMaxTextureSize; 738const GLint GLES2ImplementationTest::kMaxVaryingVectors; 739const GLint GLES2ImplementationTest::kMaxVertexAttribs; 740const GLint GLES2ImplementationTest::kMaxVertexTextureImageUnits; 741const GLint GLES2ImplementationTest::kMaxVertexUniformVectors; 742const GLint GLES2ImplementationTest::kNumCompressedTextureFormats; 743const GLint GLES2ImplementationTest::kNumShaderBinaryFormats; 744const GLuint GLES2ImplementationTest::kStartId; 745const GLuint GLES2ImplementationTest::kBuffersStartId; 746const GLuint GLES2ImplementationTest::kFramebuffersStartId; 747const GLuint GLES2ImplementationTest::kProgramsAndShadersStartId; 748const GLuint GLES2ImplementationTest::kRenderbuffersStartId; 749const GLuint GLES2ImplementationTest::kTexturesStartId; 750const GLuint GLES2ImplementationTest::kQueriesStartId; 751const GLuint GLES2ImplementationTest::kVertexArraysStartId; 752#endif 753 754TEST_F(GLES2ImplementationTest, Basic) { 755 EXPECT_TRUE(gl_->share_group() != NULL); 756} 757 758TEST_F(GLES2ImplementationTest, GetBucketContents) { 759 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 760 const uint32 kTestSize = MaxTransferBufferSize() + 32; 761 762 scoped_ptr<uint8[]> buf(new uint8 [kTestSize]); 763 uint8* expected_data = buf.get(); 764 for (uint32 ii = 0; ii < kTestSize; ++ii) { 765 expected_data[ii] = ii * 3; 766 } 767 768 struct Cmds { 769 cmd::GetBucketStart get_bucket_start; 770 cmd::SetToken set_token1; 771 cmd::GetBucketData get_bucket_data; 772 cmd::SetToken set_token2; 773 cmd::SetBucketSize set_bucket_size2; 774 }; 775 776 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 777 ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32)); 778 ExpectedMemoryInfo mem2 = GetExpectedMemory( 779 kTestSize - MaxTransferBufferSize()); 780 781 Cmds expected; 782 expected.get_bucket_start.Init( 783 kBucketId, result1.id, result1.offset, 784 MaxTransferBufferSize(), mem1.id, mem1.offset); 785 expected.set_token1.Init(GetNextToken()); 786 expected.get_bucket_data.Init( 787 kBucketId, MaxTransferBufferSize(), 788 kTestSize - MaxTransferBufferSize(), mem2.id, mem2.offset); 789 expected.set_bucket_size2.Init(kBucketId, 0); 790 expected.set_token2.Init(GetNextToken()); 791 792 EXPECT_CALL(*command_buffer(), OnFlush()) 793 .WillOnce(DoAll( 794 SetMemory(result1.ptr, kTestSize), 795 SetMemoryFromArray( 796 mem1.ptr, expected_data, MaxTransferBufferSize()))) 797 .WillOnce(SetMemoryFromArray( 798 mem2.ptr, expected_data + MaxTransferBufferSize(), 799 kTestSize - MaxTransferBufferSize())) 800 .RetiresOnSaturation(); 801 802 std::vector<int8> data; 803 GetBucketContents(kBucketId, &data); 804 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 805 ASSERT_EQ(kTestSize, data.size()); 806 EXPECT_EQ(0, memcmp(expected_data, &data[0], data.size())); 807} 808 809TEST_F(GLES2ImplementationTest, GetShaderPrecisionFormat) { 810 struct Cmds { 811 cmds::GetShaderPrecisionFormat cmd; 812 }; 813 typedef cmds::GetShaderPrecisionFormat::Result Result; 814 815 // The first call for mediump should trigger a command buffer request. 816 GLint range1[2] = {0, 0}; 817 GLint precision1 = 0; 818 Cmds expected1; 819 ExpectedMemoryInfo client_result1 = GetExpectedResultMemory(4); 820 expected1.cmd.Init(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, 821 client_result1.id, client_result1.offset); 822 Result server_result1 = {true, 14, 14, 10}; 823 EXPECT_CALL(*command_buffer(), OnFlush()) 824 .WillOnce(SetMemory(client_result1.ptr, server_result1)) 825 .RetiresOnSaturation(); 826 gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, 827 range1, &precision1); 828 const void* commands2 = GetPut(); 829 EXPECT_NE(commands_, commands2); 830 EXPECT_EQ(0, memcmp(&expected1, commands_, sizeof(expected1))); 831 EXPECT_EQ(range1[0], 14); 832 EXPECT_EQ(range1[1], 14); 833 EXPECT_EQ(precision1, 10); 834 835 // The second call for mediump should use the cached value and avoid 836 // triggering a command buffer request, so we do not expect a call to 837 // OnFlush() here. We do expect the results to be correct though. 838 GLint range2[2] = {0, 0}; 839 GLint precision2 = 0; 840 gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, 841 range2, &precision2); 842 const void* commands3 = GetPut(); 843 EXPECT_EQ(commands2, commands3); 844 EXPECT_EQ(range2[0], 14); 845 EXPECT_EQ(range2[1], 14); 846 EXPECT_EQ(precision2, 10); 847 848 // If we then make a request for highp, we should get another command 849 // buffer request since it hasn't been cached yet. 850 GLint range3[2] = {0, 0}; 851 GLint precision3 = 0; 852 Cmds expected3; 853 ExpectedMemoryInfo result3 = GetExpectedResultMemory(4); 854 expected3.cmd.Init(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, 855 result3.id, result3.offset); 856 Result result3_source = {true, 62, 62, 16}; 857 EXPECT_CALL(*command_buffer(), OnFlush()) 858 .WillOnce(SetMemory(result3.ptr, result3_source)) 859 .RetiresOnSaturation(); 860 gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, 861 range3, &precision3); 862 const void* commands4 = GetPut(); 863 EXPECT_NE(commands3, commands4); 864 EXPECT_EQ(0, memcmp(&expected3, commands3, sizeof(expected3))); 865 EXPECT_EQ(range3[0], 62); 866 EXPECT_EQ(range3[1], 62); 867 EXPECT_EQ(precision3, 16); 868} 869 870TEST_F(GLES2ImplementationTest, ShaderSource) { 871 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 872 const GLuint kShaderId = 456; 873 const char* kString1 = "foobar"; 874 const char* kString2 = "barfoo"; 875 const size_t kString1Size = strlen(kString1); 876 const size_t kString2Size = strlen(kString2); 877 const size_t kString3Size = 1; // Want the NULL; 878 const size_t kSourceSize = kString1Size + kString2Size + kString3Size; 879 const size_t kPaddedString1Size = 880 transfer_buffer_->RoundToAlignment(kString1Size); 881 const size_t kPaddedString2Size = 882 transfer_buffer_->RoundToAlignment(kString2Size); 883 const size_t kPaddedString3Size = 884 transfer_buffer_->RoundToAlignment(kString3Size); 885 struct Cmds { 886 cmd::SetBucketSize set_bucket_size; 887 cmd::SetBucketData set_bucket_data1; 888 cmd::SetToken set_token1; 889 cmd::SetBucketData set_bucket_data2; 890 cmd::SetToken set_token2; 891 cmd::SetBucketData set_bucket_data3; 892 cmd::SetToken set_token3; 893 cmds::ShaderSourceBucket shader_source_bucket; 894 cmd::SetBucketSize clear_bucket_size; 895 }; 896 897 ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); 898 ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); 899 ExpectedMemoryInfo mem3 = GetExpectedMemory(kPaddedString3Size); 900 901 Cmds expected; 902 expected.set_bucket_size.Init(kBucketId, kSourceSize); 903 expected.set_bucket_data1.Init( 904 kBucketId, 0, kString1Size, mem1.id, mem1.offset); 905 expected.set_token1.Init(GetNextToken()); 906 expected.set_bucket_data2.Init( 907 kBucketId, kString1Size, kString2Size, mem2.id, mem2.offset); 908 expected.set_token2.Init(GetNextToken()); 909 expected.set_bucket_data3.Init( 910 kBucketId, kString1Size + kString2Size, 911 kString3Size, mem3.id, mem3.offset); 912 expected.set_token3.Init(GetNextToken()); 913 expected.shader_source_bucket.Init(kShaderId, kBucketId); 914 expected.clear_bucket_size.Init(kBucketId, 0); 915 const char* strings[] = { 916 kString1, 917 kString2, 918 }; 919 gl_->ShaderSource(kShaderId, 2, strings, NULL); 920 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 921} 922 923TEST_F(GLES2ImplementationTest, GetShaderSource) { 924 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 925 const GLuint kShaderId = 456; 926 const Str7 kString = {"foobar"}; 927 const char kBad = 0x12; 928 struct Cmds { 929 cmd::SetBucketSize set_bucket_size1; 930 cmds::GetShaderSource get_shader_source; 931 cmd::GetBucketStart get_bucket_start; 932 cmd::SetToken set_token1; 933 cmd::SetBucketSize set_bucket_size2; 934 }; 935 936 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 937 ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32)); 938 939 Cmds expected; 940 expected.set_bucket_size1.Init(kBucketId, 0); 941 expected.get_shader_source.Init(kShaderId, kBucketId); 942 expected.get_bucket_start.Init( 943 kBucketId, result1.id, result1.offset, 944 MaxTransferBufferSize(), mem1.id, mem1.offset); 945 expected.set_token1.Init(GetNextToken()); 946 expected.set_bucket_size2.Init(kBucketId, 0); 947 char buf[sizeof(kString) + 1]; 948 memset(buf, kBad, sizeof(buf)); 949 950 EXPECT_CALL(*command_buffer(), OnFlush()) 951 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 952 SetMemory(mem1.ptr, kString))) 953 .RetiresOnSaturation(); 954 955 GLsizei length = 0; 956 gl_->GetShaderSource(kShaderId, sizeof(buf), &length, buf); 957 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 958 EXPECT_EQ(sizeof(kString) - 1, static_cast<size_t>(length)); 959 EXPECT_STREQ(kString.str, buf); 960 EXPECT_EQ(buf[sizeof(kString)], kBad); 961} 962 963#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 964 965TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) { 966 static const float verts[][4] = { 967 { 12.0f, 23.0f, 34.0f, 45.0f, }, 968 { 56.0f, 67.0f, 78.0f, 89.0f, }, 969 { 13.0f, 24.0f, 35.0f, 46.0f, }, 970 }; 971 struct Cmds { 972 cmds::EnableVertexAttribArray enable1; 973 cmds::EnableVertexAttribArray enable2; 974 cmds::BindBuffer bind_to_emu; 975 cmds::BufferData set_size; 976 cmds::BufferSubData copy_data1; 977 cmd::SetToken set_token1; 978 cmds::VertexAttribPointer set_pointer1; 979 cmds::BufferSubData copy_data2; 980 cmd::SetToken set_token2; 981 cmds::VertexAttribPointer set_pointer2; 982 cmds::DrawArrays draw; 983 cmds::BindBuffer restore; 984 }; 985 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 986 const GLuint kAttribIndex1 = 1; 987 const GLuint kAttribIndex2 = 3; 988 const GLint kNumComponents1 = 3; 989 const GLint kNumComponents2 = 2; 990 const GLsizei kClientStride = sizeof(verts[0]); 991 const GLint kFirst = 1; 992 const GLsizei kCount = 2; 993 const GLsizei kSize1 = 994 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 995 const GLsizei kSize2 = 996 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 997 const GLsizei kEmuOffset1 = 0; 998 const GLsizei kEmuOffset2 = kSize1; 999 const GLsizei kTotalSize = kSize1 + kSize2; 1000 1001 ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1); 1002 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2); 1003 1004 Cmds expected; 1005 expected.enable1.Init(kAttribIndex1); 1006 expected.enable2.Init(kAttribIndex2); 1007 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1008 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1009 expected.copy_data1.Init( 1010 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset); 1011 expected.set_token1.Init(GetNextToken()); 1012 expected.set_pointer1.Init( 1013 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1014 expected.copy_data2.Init( 1015 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset); 1016 expected.set_token2.Init(GetNextToken()); 1017 expected.set_pointer2.Init( 1018 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1019 expected.draw.Init(GL_POINTS, kFirst, kCount); 1020 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1021 gl_->EnableVertexAttribArray(kAttribIndex1); 1022 gl_->EnableVertexAttribArray(kAttribIndex2); 1023 gl_->VertexAttribPointer( 1024 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts); 1025 gl_->VertexAttribPointer( 1026 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts); 1027 gl_->DrawArrays(GL_POINTS, kFirst, kCount); 1028 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1029} 1030 1031TEST_F(GLES2ImplementationTest, DrawArraysInstancedANGLEClientSideBuffers) { 1032 static const float verts[][4] = { 1033 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1034 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1035 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1036 }; 1037 struct Cmds { 1038 cmds::EnableVertexAttribArray enable1; 1039 cmds::EnableVertexAttribArray enable2; 1040 cmds::VertexAttribDivisorANGLE divisor; 1041 cmds::BindBuffer bind_to_emu; 1042 cmds::BufferData set_size; 1043 cmds::BufferSubData copy_data1; 1044 cmd::SetToken set_token1; 1045 cmds::VertexAttribPointer set_pointer1; 1046 cmds::BufferSubData copy_data2; 1047 cmd::SetToken set_token2; 1048 cmds::VertexAttribPointer set_pointer2; 1049 cmds::DrawArraysInstancedANGLE draw; 1050 cmds::BindBuffer restore; 1051 }; 1052 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1053 const GLuint kAttribIndex1 = 1; 1054 const GLuint kAttribIndex2 = 3; 1055 const GLint kNumComponents1 = 3; 1056 const GLint kNumComponents2 = 2; 1057 const GLsizei kClientStride = sizeof(verts[0]); 1058 const GLint kFirst = 1; 1059 const GLsizei kCount = 2; 1060 const GLuint kDivisor = 1; 1061 const GLsizei kSize1 = 1062 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1063 const GLsizei kSize2 = 1064 1 * kNumComponents2 * sizeof(verts[0][0]); 1065 const GLsizei kEmuOffset1 = 0; 1066 const GLsizei kEmuOffset2 = kSize1; 1067 const GLsizei kTotalSize = kSize1 + kSize2; 1068 1069 ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1); 1070 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2); 1071 1072 Cmds expected; 1073 expected.enable1.Init(kAttribIndex1); 1074 expected.enable2.Init(kAttribIndex2); 1075 expected.divisor.Init(kAttribIndex2, kDivisor); 1076 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1077 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1078 expected.copy_data1.Init( 1079 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset); 1080 expected.set_token1.Init(GetNextToken()); 1081 expected.set_pointer1.Init( 1082 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1083 expected.copy_data2.Init( 1084 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset); 1085 expected.set_token2.Init(GetNextToken()); 1086 expected.set_pointer2.Init( 1087 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1088 expected.draw.Init(GL_POINTS, kFirst, kCount, 1); 1089 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1090 gl_->EnableVertexAttribArray(kAttribIndex1); 1091 gl_->EnableVertexAttribArray(kAttribIndex2); 1092 gl_->VertexAttribPointer( 1093 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts); 1094 gl_->VertexAttribPointer( 1095 kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts); 1096 gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor); 1097 gl_->DrawArraysInstancedANGLE(GL_POINTS, kFirst, kCount, 1); 1098 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1099} 1100 1101TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) { 1102 static const float verts[][4] = { 1103 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1104 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1105 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1106 }; 1107 static const uint16 indices[] = { 1108 1, 2, 1109 }; 1110 struct Cmds { 1111 cmds::EnableVertexAttribArray enable1; 1112 cmds::EnableVertexAttribArray enable2; 1113 cmds::BindBuffer bind_to_index_emu; 1114 cmds::BufferData set_index_size; 1115 cmds::BufferSubData copy_data0; 1116 cmd::SetToken set_token0; 1117 cmds::BindBuffer bind_to_emu; 1118 cmds::BufferData set_size; 1119 cmds::BufferSubData copy_data1; 1120 cmd::SetToken set_token1; 1121 cmds::VertexAttribPointer set_pointer1; 1122 cmds::BufferSubData copy_data2; 1123 cmd::SetToken set_token2; 1124 cmds::VertexAttribPointer set_pointer2; 1125 cmds::DrawElements draw; 1126 cmds::BindBuffer restore; 1127 cmds::BindBuffer restore_element; 1128 }; 1129 const GLsizei kIndexSize = sizeof(indices); 1130 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1131 const GLuint kEmuIndexBufferId = 1132 GLES2Implementation::kClientSideElementArrayId; 1133 const GLuint kAttribIndex1 = 1; 1134 const GLuint kAttribIndex2 = 3; 1135 const GLint kNumComponents1 = 3; 1136 const GLint kNumComponents2 = 2; 1137 const GLsizei kClientStride = sizeof(verts[0]); 1138 const GLsizei kCount = 2; 1139 const GLsizei kSize1 = 1140 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1141 const GLsizei kSize2 = 1142 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 1143 const GLsizei kEmuOffset1 = 0; 1144 const GLsizei kEmuOffset2 = kSize1; 1145 const GLsizei kTotalSize = kSize1 + kSize2; 1146 1147 ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); 1148 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1149 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1150 1151 Cmds expected; 1152 expected.enable1.Init(kAttribIndex1); 1153 expected.enable2.Init(kAttribIndex2); 1154 expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); 1155 expected.set_index_size.Init( 1156 GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); 1157 expected.copy_data0.Init( 1158 GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); 1159 expected.set_token0.Init(GetNextToken()); 1160 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1161 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1162 expected.copy_data1.Init( 1163 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1164 expected.set_token1.Init(GetNextToken()); 1165 expected.set_pointer1.Init( 1166 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1167 expected.copy_data2.Init( 1168 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1169 expected.set_token2.Init(GetNextToken()); 1170 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1171 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1172 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0); 1173 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1174 expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); 1175 gl_->EnableVertexAttribArray(kAttribIndex1); 1176 gl_->EnableVertexAttribArray(kAttribIndex2); 1177 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1178 GL_FLOAT, GL_FALSE, kClientStride, verts); 1179 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1180 GL_FLOAT, GL_FALSE, kClientStride, verts); 1181 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices); 1182 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1183} 1184 1185TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersIndexUint) { 1186 static const float verts[][4] = { 1187 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1188 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1189 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1190 }; 1191 static const uint32 indices[] = { 1192 1, 2, 1193 }; 1194 struct Cmds { 1195 cmds::EnableVertexAttribArray enable1; 1196 cmds::EnableVertexAttribArray enable2; 1197 cmds::BindBuffer bind_to_index_emu; 1198 cmds::BufferData set_index_size; 1199 cmds::BufferSubData copy_data0; 1200 cmd::SetToken set_token0; 1201 cmds::BindBuffer bind_to_emu; 1202 cmds::BufferData set_size; 1203 cmds::BufferSubData copy_data1; 1204 cmd::SetToken set_token1; 1205 cmds::VertexAttribPointer set_pointer1; 1206 cmds::BufferSubData copy_data2; 1207 cmd::SetToken set_token2; 1208 cmds::VertexAttribPointer set_pointer2; 1209 cmds::DrawElements draw; 1210 cmds::BindBuffer restore; 1211 cmds::BindBuffer restore_element; 1212 }; 1213 const GLsizei kIndexSize = sizeof(indices); 1214 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1215 const GLuint kEmuIndexBufferId = 1216 GLES2Implementation::kClientSideElementArrayId; 1217 const GLuint kAttribIndex1 = 1; 1218 const GLuint kAttribIndex2 = 3; 1219 const GLint kNumComponents1 = 3; 1220 const GLint kNumComponents2 = 2; 1221 const GLsizei kClientStride = sizeof(verts[0]); 1222 const GLsizei kCount = 2; 1223 const GLsizei kSize1 = 1224 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1225 const GLsizei kSize2 = 1226 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 1227 const GLsizei kEmuOffset1 = 0; 1228 const GLsizei kEmuOffset2 = kSize1; 1229 const GLsizei kTotalSize = kSize1 + kSize2; 1230 1231 ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); 1232 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1233 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1234 1235 Cmds expected; 1236 expected.enable1.Init(kAttribIndex1); 1237 expected.enable2.Init(kAttribIndex2); 1238 expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); 1239 expected.set_index_size.Init( 1240 GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); 1241 expected.copy_data0.Init( 1242 GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); 1243 expected.set_token0.Init(GetNextToken()); 1244 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1245 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1246 expected.copy_data1.Init( 1247 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1248 expected.set_token1.Init(GetNextToken()); 1249 expected.set_pointer1.Init( 1250 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1251 expected.copy_data2.Init( 1252 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1253 expected.set_token2.Init(GetNextToken()); 1254 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1255 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1256 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_INT, 0); 1257 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1258 expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); 1259 gl_->EnableVertexAttribArray(kAttribIndex1); 1260 gl_->EnableVertexAttribArray(kAttribIndex2); 1261 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1262 GL_FLOAT, GL_FALSE, kClientStride, verts); 1263 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1264 GL_FLOAT, GL_FALSE, kClientStride, verts); 1265 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices); 1266 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1267} 1268 1269TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersInvalidIndexUint) { 1270 static const float verts[][4] = { 1271 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1272 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1273 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1274 }; 1275 static const uint32 indices[] = { 1276 1, 0x90000000 1277 }; 1278 1279 const GLuint kAttribIndex1 = 1; 1280 const GLuint kAttribIndex2 = 3; 1281 const GLint kNumComponents1 = 3; 1282 const GLint kNumComponents2 = 2; 1283 const GLsizei kClientStride = sizeof(verts[0]); 1284 const GLsizei kCount = 2; 1285 1286 EXPECT_CALL(*command_buffer(), OnFlush()) 1287 .Times(1) 1288 .RetiresOnSaturation(); 1289 1290 gl_->EnableVertexAttribArray(kAttribIndex1); 1291 gl_->EnableVertexAttribArray(kAttribIndex2); 1292 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1293 GL_FLOAT, GL_FALSE, kClientStride, verts); 1294 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1295 GL_FLOAT, GL_FALSE, kClientStride, verts); 1296 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices); 1297 1298 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError()); 1299} 1300 1301TEST_F(GLES2ImplementationTest, 1302 DrawElementsClientSideBuffersServiceSideIndices) { 1303 static const float verts[][4] = { 1304 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1305 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1306 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1307 }; 1308 struct Cmds { 1309 cmds::EnableVertexAttribArray enable1; 1310 cmds::EnableVertexAttribArray enable2; 1311 cmds::BindBuffer bind_to_index; 1312 cmds::GetMaxValueInBufferCHROMIUM get_max; 1313 cmds::BindBuffer bind_to_emu; 1314 cmds::BufferData set_size; 1315 cmds::BufferSubData copy_data1; 1316 cmd::SetToken set_token1; 1317 cmds::VertexAttribPointer set_pointer1; 1318 cmds::BufferSubData copy_data2; 1319 cmd::SetToken set_token2; 1320 cmds::VertexAttribPointer set_pointer2; 1321 cmds::DrawElements draw; 1322 cmds::BindBuffer restore; 1323 }; 1324 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1325 const GLuint kClientIndexBufferId = 0x789; 1326 const GLuint kIndexOffset = 0x40; 1327 const GLuint kMaxIndex = 2; 1328 const GLuint kAttribIndex1 = 1; 1329 const GLuint kAttribIndex2 = 3; 1330 const GLint kNumComponents1 = 3; 1331 const GLint kNumComponents2 = 2; 1332 const GLsizei kClientStride = sizeof(verts[0]); 1333 const GLsizei kCount = 2; 1334 const GLsizei kSize1 = 1335 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1336 const GLsizei kSize2 = 1337 arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); 1338 const GLsizei kEmuOffset1 = 0; 1339 const GLsizei kEmuOffset2 = kSize1; 1340 const GLsizei kTotalSize = kSize1 + kSize2; 1341 1342 ExpectedMemoryInfo mem1 = GetExpectedResultMemory(sizeof(uint32)); 1343 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1344 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1345 1346 1347 Cmds expected; 1348 expected.enable1.Init(kAttribIndex1); 1349 expected.enable2.Init(kAttribIndex2); 1350 expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); 1351 expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT, 1352 kIndexOffset, mem1.id, mem1.offset); 1353 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1354 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1355 expected.copy_data1.Init( 1356 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1357 expected.set_token1.Init(GetNextToken()); 1358 expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, 1359 GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1360 expected.copy_data2.Init( 1361 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1362 expected.set_token2.Init(GetNextToken()); 1363 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1364 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1365 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, kIndexOffset); 1366 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1367 1368 EXPECT_CALL(*command_buffer(), OnFlush()) 1369 .WillOnce(SetMemory(mem1.ptr,kMaxIndex)) 1370 .RetiresOnSaturation(); 1371 1372 gl_->EnableVertexAttribArray(kAttribIndex1); 1373 gl_->EnableVertexAttribArray(kAttribIndex2); 1374 gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); 1375 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1376 GL_FLOAT, GL_FALSE, kClientStride, verts); 1377 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1378 GL_FLOAT, GL_FALSE, kClientStride, verts); 1379 gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 1380 reinterpret_cast<const void*>(kIndexOffset)); 1381 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1382} 1383 1384TEST_F(GLES2ImplementationTest, DrawElementsInstancedANGLEClientSideBuffers) { 1385 static const float verts[][4] = { 1386 { 12.0f, 23.0f, 34.0f, 45.0f, }, 1387 { 56.0f, 67.0f, 78.0f, 89.0f, }, 1388 { 13.0f, 24.0f, 35.0f, 46.0f, }, 1389 }; 1390 static const uint16 indices[] = { 1391 1, 2, 1392 }; 1393 struct Cmds { 1394 cmds::EnableVertexAttribArray enable1; 1395 cmds::EnableVertexAttribArray enable2; 1396 cmds::VertexAttribDivisorANGLE divisor; 1397 cmds::BindBuffer bind_to_index_emu; 1398 cmds::BufferData set_index_size; 1399 cmds::BufferSubData copy_data0; 1400 cmd::SetToken set_token0; 1401 cmds::BindBuffer bind_to_emu; 1402 cmds::BufferData set_size; 1403 cmds::BufferSubData copy_data1; 1404 cmd::SetToken set_token1; 1405 cmds::VertexAttribPointer set_pointer1; 1406 cmds::BufferSubData copy_data2; 1407 cmd::SetToken set_token2; 1408 cmds::VertexAttribPointer set_pointer2; 1409 cmds::DrawElementsInstancedANGLE draw; 1410 cmds::BindBuffer restore; 1411 cmds::BindBuffer restore_element; 1412 }; 1413 const GLsizei kIndexSize = sizeof(indices); 1414 const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; 1415 const GLuint kEmuIndexBufferId = 1416 GLES2Implementation::kClientSideElementArrayId; 1417 const GLuint kAttribIndex1 = 1; 1418 const GLuint kAttribIndex2 = 3; 1419 const GLint kNumComponents1 = 3; 1420 const GLint kNumComponents2 = 2; 1421 const GLsizei kClientStride = sizeof(verts[0]); 1422 const GLsizei kCount = 2; 1423 const GLsizei kSize1 = 1424 arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); 1425 const GLsizei kSize2 = 1426 1 * kNumComponents2 * sizeof(verts[0][0]); 1427 const GLuint kDivisor = 1; 1428 const GLsizei kEmuOffset1 = 0; 1429 const GLsizei kEmuOffset2 = kSize1; 1430 const GLsizei kTotalSize = kSize1 + kSize2; 1431 1432 ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize); 1433 ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1); 1434 ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2); 1435 1436 Cmds expected; 1437 expected.enable1.Init(kAttribIndex1); 1438 expected.enable2.Init(kAttribIndex2); 1439 expected.divisor.Init(kAttribIndex2, kDivisor); 1440 expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); 1441 expected.set_index_size.Init( 1442 GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); 1443 expected.copy_data0.Init( 1444 GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset); 1445 expected.set_token0.Init(GetNextToken()); 1446 expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); 1447 expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); 1448 expected.copy_data1.Init( 1449 GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset); 1450 expected.set_token1.Init(GetNextToken()); 1451 expected.set_pointer1.Init( 1452 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); 1453 expected.copy_data2.Init( 1454 GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset); 1455 expected.set_token2.Init(GetNextToken()); 1456 expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, 1457 GL_FLOAT, GL_FALSE, 0, kEmuOffset2); 1458 expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0, 1); 1459 expected.restore.Init(GL_ARRAY_BUFFER, 0); 1460 expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); 1461 gl_->EnableVertexAttribArray(kAttribIndex1); 1462 gl_->EnableVertexAttribArray(kAttribIndex2); 1463 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1464 GL_FLOAT, GL_FALSE, kClientStride, verts); 1465 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1466 GL_FLOAT, GL_FALSE, kClientStride, verts); 1467 gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor); 1468 gl_->DrawElementsInstancedANGLE( 1469 GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices, 1); 1470 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1471} 1472 1473TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) { 1474 static const float verts[1] = { 0.0f, }; 1475 const GLuint kAttribIndex1 = 1; 1476 const GLuint kAttribIndex2 = 3; 1477 const GLint kNumComponents1 = 3; 1478 const GLint kNumComponents2 = 2; 1479 const GLsizei kStride1 = 12; 1480 const GLsizei kStride2 = 0; 1481 const GLuint kBufferId = 0x123; 1482 const GLint kOffset2 = 0x456; 1483 1484 // It's all cached on the client side so no get commands are issued. 1485 struct Cmds { 1486 cmds::BindBuffer bind; 1487 cmds::VertexAttribPointer set_pointer; 1488 }; 1489 1490 Cmds expected; 1491 expected.bind.Init(GL_ARRAY_BUFFER, kBufferId); 1492 expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 1493 kStride2, kOffset2); 1494 1495 // Set one client side buffer. 1496 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1497 GL_FLOAT, GL_FALSE, kStride1, verts); 1498 // Set one VBO 1499 gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); 1500 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1501 GL_FLOAT, GL_FALSE, kStride2, 1502 reinterpret_cast<const void*>(kOffset2)); 1503 // now get them both. 1504 void* ptr1 = NULL; 1505 void* ptr2 = NULL; 1506 1507 gl_->GetVertexAttribPointerv( 1508 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr1); 1509 gl_->GetVertexAttribPointerv( 1510 kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr2); 1511 1512 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1513 EXPECT_TRUE(static_cast<const void*>(&verts) == ptr1); 1514 EXPECT_TRUE(ptr2 == reinterpret_cast<void*>(kOffset2)); 1515} 1516 1517TEST_F(GLES2ImplementationTest, GetVertexAttrib) { 1518 static const float verts[1] = { 0.0f, }; 1519 const GLuint kAttribIndex1 = 1; 1520 const GLuint kAttribIndex2 = 3; 1521 const GLint kNumComponents1 = 3; 1522 const GLint kNumComponents2 = 2; 1523 const GLsizei kStride1 = 12; 1524 const GLsizei kStride2 = 0; 1525 const GLuint kBufferId = 0x123; 1526 const GLint kOffset2 = 0x456; 1527 1528 // Only one set and one get because the client side buffer's info is stored 1529 // on the client side. 1530 struct Cmds { 1531 cmds::EnableVertexAttribArray enable; 1532 cmds::BindBuffer bind; 1533 cmds::VertexAttribPointer set_pointer; 1534 cmds::GetVertexAttribfv get2; // for getting the value from attrib1 1535 }; 1536 1537 ExpectedMemoryInfo mem2 = GetExpectedResultMemory(16); 1538 1539 Cmds expected; 1540 expected.enable.Init(kAttribIndex1); 1541 expected.bind.Init(GL_ARRAY_BUFFER, kBufferId); 1542 expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 1543 kStride2, kOffset2); 1544 expected.get2.Init(kAttribIndex1, 1545 GL_CURRENT_VERTEX_ATTRIB, 1546 mem2.id, mem2.offset); 1547 1548 FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f); 1549 1550 // One call to flush to wait for last call to GetVertexAttribiv 1551 // as others are all cached. 1552 EXPECT_CALL(*command_buffer(), OnFlush()) 1553 .WillOnce(SetMemory( 1554 mem2.ptr, SizedResultHelper<FourFloats>(current_attrib))) 1555 .RetiresOnSaturation(); 1556 1557 gl_->EnableVertexAttribArray(kAttribIndex1); 1558 // Set one client side buffer. 1559 gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, 1560 GL_FLOAT, GL_FALSE, kStride1, verts); 1561 // Set one VBO 1562 gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); 1563 gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, 1564 GL_FLOAT, GL_FALSE, kStride2, 1565 reinterpret_cast<const void*>(kOffset2)); 1566 // first get the service side once to see that we make a command 1567 GLint buffer_id = 0; 1568 GLint enabled = 0; 1569 GLint size = 0; 1570 GLint stride = 0; 1571 GLint type = 0; 1572 GLint normalized = 1; 1573 float current[4] = { 0.0f, }; 1574 1575 gl_->GetVertexAttribiv( 1576 kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id); 1577 EXPECT_EQ(kBufferId, static_cast<GLuint>(buffer_id)); 1578 gl_->GetVertexAttribiv( 1579 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id); 1580 gl_->GetVertexAttribiv( 1581 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled); 1582 gl_->GetVertexAttribiv( 1583 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size); 1584 gl_->GetVertexAttribiv( 1585 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride); 1586 gl_->GetVertexAttribiv( 1587 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type); 1588 gl_->GetVertexAttribiv( 1589 kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized); 1590 gl_->GetVertexAttribfv( 1591 kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, ¤t[0]); 1592 1593 EXPECT_EQ(0, buffer_id); 1594 EXPECT_EQ(GL_TRUE, enabled); 1595 EXPECT_EQ(kNumComponents1, size); 1596 EXPECT_EQ(kStride1, stride); 1597 EXPECT_EQ(GL_FLOAT, type); 1598 EXPECT_EQ(GL_FALSE, normalized); 1599 EXPECT_EQ(0, memcmp(¤t_attrib, ¤t, sizeof(current_attrib))); 1600 1601 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1602} 1603 1604TEST_F(GLES2ImplementationTest, ReservedIds) { 1605 // Only the get error command should be issued. 1606 struct Cmds { 1607 cmds::GetError get; 1608 }; 1609 Cmds expected; 1610 1611 ExpectedMemoryInfo mem1 = GetExpectedResultMemory( 1612 sizeof(cmds::GetError::Result)); 1613 1614 expected.get.Init(mem1.id, mem1.offset); 1615 1616 // One call to flush to wait for GetError 1617 EXPECT_CALL(*command_buffer(), OnFlush()) 1618 .WillOnce(SetMemory(mem1.ptr, GLuint(GL_NO_ERROR))) 1619 .RetiresOnSaturation(); 1620 1621 gl_->BindBuffer( 1622 GL_ARRAY_BUFFER, 1623 GLES2Implementation::kClientSideArrayId); 1624 gl_->BindBuffer( 1625 GL_ARRAY_BUFFER, 1626 GLES2Implementation::kClientSideElementArrayId); 1627 GLenum err = gl_->GetError(); 1628 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), err); 1629 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1630} 1631 1632#endif // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 1633 1634TEST_F(GLES2ImplementationTest, ReadPixels2Reads) { 1635 struct Cmds { 1636 cmds::ReadPixels read1; 1637 cmd::SetToken set_token1; 1638 cmds::ReadPixels read2; 1639 cmd::SetToken set_token2; 1640 }; 1641 const GLint kBytesPerPixel = 4; 1642 const GLint kWidth = 1643 (kTransferBufferSize - GLES2Implementation::kStartingOffset) / 1644 kBytesPerPixel; 1645 const GLint kHeight = 2; 1646 const GLenum kFormat = GL_RGBA; 1647 const GLenum kType = GL_UNSIGNED_BYTE; 1648 1649 ExpectedMemoryInfo mem1 = 1650 GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel); 1651 ExpectedMemoryInfo result1 = 1652 GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result)); 1653 ExpectedMemoryInfo mem2 = 1654 GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel); 1655 ExpectedMemoryInfo result2 = 1656 GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result)); 1657 1658 Cmds expected; 1659 expected.read1.Init( 1660 0, 0, kWidth, kHeight / 2, kFormat, kType, 1661 mem1.id, mem1.offset, result1.id, result1.offset, 1662 false); 1663 expected.set_token1.Init(GetNextToken()); 1664 expected.read2.Init( 1665 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, 1666 mem2.id, mem2.offset, result2.id, result2.offset, false); 1667 expected.set_token2.Init(GetNextToken()); 1668 scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]); 1669 1670 EXPECT_CALL(*command_buffer(), OnFlush()) 1671 .WillOnce(SetMemory(result1.ptr, static_cast<uint32>(1))) 1672 .WillOnce(SetMemory(result2.ptr, static_cast<uint32>(1))) 1673 .RetiresOnSaturation(); 1674 1675 gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get()); 1676 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1677} 1678 1679TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) { 1680 struct Cmds { 1681 cmds::ReadPixels read; 1682 cmd::SetToken set_token; 1683 }; 1684 const GLint kBytesPerPixel = 4; 1685 const GLint kWidth = 2; 1686 const GLint kHeight = 2; 1687 const GLenum kFormat = 0; 1688 const GLenum kType = 0; 1689 1690 ExpectedMemoryInfo mem1 = 1691 GetExpectedMemory(kWidth * kHeight * kBytesPerPixel); 1692 ExpectedMemoryInfo result1 = 1693 GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result)); 1694 1695 Cmds expected; 1696 expected.read.Init( 1697 0, 0, kWidth, kHeight, kFormat, kType, 1698 mem1.id, mem1.offset, result1.id, result1.offset, false); 1699 expected.set_token.Init(GetNextToken()); 1700 scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]); 1701 1702 EXPECT_CALL(*command_buffer(), OnFlush()) 1703 .Times(1) 1704 .RetiresOnSaturation(); 1705 1706 gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get()); 1707} 1708 1709TEST_F(GLES2ImplementationTest, FreeUnusedSharedMemory) { 1710 struct Cmds { 1711 cmds::BufferSubData buf; 1712 cmd::SetToken set_token; 1713 }; 1714 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; 1715 const GLintptr kOffset = 15; 1716 const GLsizeiptr kSize = 16; 1717 1718 ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize); 1719 1720 Cmds expected; 1721 expected.buf.Init( 1722 kTarget, kOffset, kSize, mem1.id, mem1.offset); 1723 expected.set_token.Init(GetNextToken()); 1724 1725 void* mem = gl_->MapBufferSubDataCHROMIUM( 1726 kTarget, kOffset, kSize, GL_WRITE_ONLY); 1727 ASSERT_TRUE(mem != NULL); 1728 gl_->UnmapBufferSubDataCHROMIUM(mem); 1729 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_)) 1730 .Times(1) 1731 .RetiresOnSaturation(); 1732 gl_->FreeUnusedSharedMemory(); 1733} 1734 1735TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUM) { 1736 struct Cmds { 1737 cmds::BufferSubData buf; 1738 cmd::SetToken set_token; 1739 }; 1740 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; 1741 const GLintptr kOffset = 15; 1742 const GLsizeiptr kSize = 16; 1743 1744 uint32 offset = 0; 1745 Cmds expected; 1746 expected.buf.Init( 1747 kTarget, kOffset, kSize, 1748 command_buffer()->GetNextFreeTransferBufferId(), offset); 1749 expected.set_token.Init(GetNextToken()); 1750 1751 void* mem = gl_->MapBufferSubDataCHROMIUM( 1752 kTarget, kOffset, kSize, GL_WRITE_ONLY); 1753 ASSERT_TRUE(mem != NULL); 1754 gl_->UnmapBufferSubDataCHROMIUM(mem); 1755 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1756} 1757 1758TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUMBadArgs) { 1759 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER; 1760 const GLintptr kOffset = 15; 1761 const GLsizeiptr kSize = 16; 1762 1763 ExpectedMemoryInfo result1 = 1764 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1765 ExpectedMemoryInfo result2 = 1766 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1767 ExpectedMemoryInfo result3 = 1768 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1769 ExpectedMemoryInfo result4 = 1770 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1771 1772 // Calls to flush to wait for GetError 1773 EXPECT_CALL(*command_buffer(), OnFlush()) 1774 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1775 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1776 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 1777 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 1778 .RetiresOnSaturation(); 1779 1780 void* mem; 1781 mem = gl_->MapBufferSubDataCHROMIUM(kTarget, -1, kSize, GL_WRITE_ONLY); 1782 ASSERT_TRUE(mem == NULL); 1783 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1784 mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, -1, GL_WRITE_ONLY); 1785 ASSERT_TRUE(mem == NULL); 1786 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1787 mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, kSize, GL_READ_ONLY); 1788 ASSERT_TRUE(mem == NULL); 1789 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError()); 1790 const char* kPtr = "something"; 1791 gl_->UnmapBufferSubDataCHROMIUM(kPtr); 1792 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1793} 1794 1795TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUM) { 1796 struct Cmds { 1797 cmds::TexSubImage2D tex; 1798 cmd::SetToken set_token; 1799 }; 1800 const GLint kLevel = 1; 1801 const GLint kXOffset = 2; 1802 const GLint kYOffset = 3; 1803 const GLint kWidth = 4; 1804 const GLint kHeight = 5; 1805 const GLenum kFormat = GL_RGBA; 1806 const GLenum kType = GL_UNSIGNED_BYTE; 1807 1808 uint32 offset = 0; 1809 Cmds expected; 1810 expected.tex.Init( 1811 GL_TEXTURE_2D, kLevel, kXOffset, kYOffset, kWidth, kHeight, kFormat, 1812 kType, 1813 command_buffer()->GetNextFreeTransferBufferId(), offset, GL_FALSE); 1814 expected.set_token.Init(GetNextToken()); 1815 1816 void* mem = gl_->MapTexSubImage2DCHROMIUM( 1817 GL_TEXTURE_2D, 1818 kLevel, 1819 kXOffset, 1820 kYOffset, 1821 kWidth, 1822 kHeight, 1823 kFormat, 1824 kType, 1825 GL_WRITE_ONLY); 1826 ASSERT_TRUE(mem != NULL); 1827 gl_->UnmapTexSubImage2DCHROMIUM(mem); 1828 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1829} 1830 1831TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUMBadArgs) { 1832 const GLint kLevel = 1; 1833 const GLint kXOffset = 2; 1834 const GLint kYOffset = 3; 1835 const GLint kWidth = 4; 1836 const GLint kHeight = 5; 1837 const GLenum kFormat = GL_RGBA; 1838 const GLenum kType = GL_UNSIGNED_BYTE; 1839 1840 ExpectedMemoryInfo result1 = 1841 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1842 ExpectedMemoryInfo result2 = 1843 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1844 ExpectedMemoryInfo result3 = 1845 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1846 ExpectedMemoryInfo result4 = 1847 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1848 ExpectedMemoryInfo result5 = 1849 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1850 ExpectedMemoryInfo result6 = 1851 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1852 ExpectedMemoryInfo result7 = 1853 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 1854 1855 // Calls to flush to wait for GetError 1856 EXPECT_CALL(*command_buffer(), OnFlush()) 1857 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1858 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 1859 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 1860 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 1861 .WillOnce(SetMemory(result5.ptr, GLuint(GL_NO_ERROR))) 1862 .WillOnce(SetMemory(result6.ptr, GLuint(GL_NO_ERROR))) 1863 .WillOnce(SetMemory(result7.ptr, GLuint(GL_NO_ERROR))) 1864 .RetiresOnSaturation(); 1865 1866 void* mem; 1867 mem = gl_->MapTexSubImage2DCHROMIUM( 1868 GL_TEXTURE_2D, 1869 -1, 1870 kXOffset, 1871 kYOffset, 1872 kWidth, 1873 kHeight, 1874 kFormat, 1875 kType, 1876 GL_WRITE_ONLY); 1877 EXPECT_TRUE(mem == NULL); 1878 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1879 mem = gl_->MapTexSubImage2DCHROMIUM( 1880 GL_TEXTURE_2D, 1881 kLevel, 1882 -1, 1883 kYOffset, 1884 kWidth, 1885 kHeight, 1886 kFormat, 1887 kType, 1888 GL_WRITE_ONLY); 1889 EXPECT_TRUE(mem == NULL); 1890 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1891 mem = gl_->MapTexSubImage2DCHROMIUM( 1892 GL_TEXTURE_2D, 1893 kLevel, 1894 kXOffset, 1895 -1, 1896 kWidth, 1897 kHeight, 1898 kFormat, 1899 kType, 1900 GL_WRITE_ONLY); 1901 EXPECT_TRUE(mem == NULL); 1902 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1903 mem = gl_->MapTexSubImage2DCHROMIUM( 1904 GL_TEXTURE_2D, 1905 kLevel, 1906 kXOffset, 1907 kYOffset, 1908 -1, 1909 kHeight, 1910 kFormat, 1911 kType, 1912 GL_WRITE_ONLY); 1913 EXPECT_TRUE(mem == NULL); 1914 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1915 mem = gl_->MapTexSubImage2DCHROMIUM( 1916 GL_TEXTURE_2D, 1917 kLevel, 1918 kXOffset, 1919 kYOffset, 1920 kWidth, 1921 -1, 1922 kFormat, 1923 kType, 1924 GL_WRITE_ONLY); 1925 EXPECT_TRUE(mem == NULL); 1926 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1927 mem = gl_->MapTexSubImage2DCHROMIUM( 1928 GL_TEXTURE_2D, 1929 kLevel, 1930 kXOffset, 1931 kYOffset, 1932 kWidth, 1933 kHeight, 1934 kFormat, 1935 kType, 1936 GL_READ_ONLY); 1937 EXPECT_TRUE(mem == NULL); 1938 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError()); 1939 const char* kPtr = "something"; 1940 gl_->UnmapTexSubImage2DCHROMIUM(kPtr); 1941 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 1942} 1943 1944TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMValidArgs) { 1945 const GLenum pnames[] = { 1946 GL_DEPTH_WRITEMASK, 1947 GL_COLOR_WRITEMASK, 1948 GL_STENCIL_WRITEMASK, 1949 }; 1950 const GLint num_results = 6; 1951 GLint results[num_results + 1]; 1952 struct Cmds { 1953 cmds::GetMultipleIntegervCHROMIUM get_multiple; 1954 cmd::SetToken set_token; 1955 }; 1956 const GLsizei kNumPnames = arraysize(pnames); 1957 const GLsizeiptr kResultsSize = num_results * sizeof(results[0]); 1958 const size_t kPNamesSize = kNumPnames * sizeof(pnames[0]); 1959 1960 ExpectedMemoryInfo mem1 = GetExpectedMemory(kPNamesSize + kResultsSize); 1961 ExpectedMemoryInfo result1 = GetExpectedResultMemory( 1962 sizeof(cmds::GetError::Result)); 1963 1964 const uint32 kPnamesOffset = mem1.offset; 1965 const uint32 kResultsOffset = mem1.offset + kPNamesSize; 1966 Cmds expected; 1967 expected.get_multiple.Init( 1968 mem1.id, kPnamesOffset, kNumPnames, 1969 mem1.id, kResultsOffset, kResultsSize); 1970 expected.set_token.Init(GetNextToken()); 1971 1972 const GLint kSentinel = 0x12345678; 1973 memset(results, 0, sizeof(results)); 1974 results[num_results] = kSentinel; 1975 const GLint returned_results[] = { 1976 1, 0, 1, 0, 1, -1, 1977 }; 1978 // One call to flush to wait for results 1979 EXPECT_CALL(*command_buffer(), OnFlush()) 1980 .WillOnce(SetMemoryFromArray(mem1.ptr + kPNamesSize, 1981 returned_results, sizeof(returned_results))) 1982 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 1983 .RetiresOnSaturation(); 1984 1985 gl_->GetMultipleIntegervCHROMIUM( 1986 &pnames[0], kNumPnames, &results[0], kResultsSize); 1987 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 1988 EXPECT_EQ(0, memcmp(&returned_results, results, sizeof(returned_results))); 1989 EXPECT_EQ(kSentinel, results[num_results]); 1990 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 1991} 1992 1993TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMBadArgs) { 1994 GLenum pnames[] = { 1995 GL_DEPTH_WRITEMASK, 1996 GL_COLOR_WRITEMASK, 1997 GL_STENCIL_WRITEMASK, 1998 }; 1999 const GLint num_results = 6; 2000 GLint results[num_results + 1]; 2001 const GLsizei kNumPnames = arraysize(pnames); 2002 const GLsizeiptr kResultsSize = num_results * sizeof(results[0]); 2003 2004 ExpectedMemoryInfo result1 = 2005 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2006 ExpectedMemoryInfo result2 = 2007 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2008 ExpectedMemoryInfo result3 = 2009 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2010 ExpectedMemoryInfo result4 = 2011 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2012 2013 // Calls to flush to wait for GetError 2014 EXPECT_CALL(*command_buffer(), OnFlush()) 2015 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 2016 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 2017 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 2018 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 2019 .RetiresOnSaturation(); 2020 2021 const GLint kSentinel = 0x12345678; 2022 memset(results, 0, sizeof(results)); 2023 results[num_results] = kSentinel; 2024 // try bad size. 2025 gl_->GetMultipleIntegervCHROMIUM( 2026 &pnames[0], kNumPnames, &results[0], kResultsSize + 1); 2027 EXPECT_TRUE(NoCommandsWritten()); 2028 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 2029 EXPECT_EQ(0, results[0]); 2030 EXPECT_EQ(kSentinel, results[num_results]); 2031 // try bad size. 2032 ClearCommands(); 2033 gl_->GetMultipleIntegervCHROMIUM( 2034 &pnames[0], kNumPnames, &results[0], kResultsSize - 1); 2035 EXPECT_TRUE(NoCommandsWritten()); 2036 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 2037 EXPECT_EQ(0, results[0]); 2038 EXPECT_EQ(kSentinel, results[num_results]); 2039 // try uncleared results. 2040 ClearCommands(); 2041 results[2] = 1; 2042 gl_->GetMultipleIntegervCHROMIUM( 2043 &pnames[0], kNumPnames, &results[0], kResultsSize); 2044 EXPECT_TRUE(NoCommandsWritten()); 2045 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 2046 EXPECT_EQ(0, results[0]); 2047 EXPECT_EQ(kSentinel, results[num_results]); 2048 // try bad enum results. 2049 ClearCommands(); 2050 results[2] = 0; 2051 pnames[1] = GL_TRUE; 2052 gl_->GetMultipleIntegervCHROMIUM( 2053 &pnames[0], kNumPnames, &results[0], kResultsSize); 2054 EXPECT_TRUE(NoCommandsWritten()); 2055 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError()); 2056 EXPECT_EQ(0, results[0]); 2057 EXPECT_EQ(kSentinel, results[num_results]); 2058} 2059 2060TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMGoodArgs) { 2061 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 2062 const GLuint kProgramId = 123; 2063 const char kBad = 0x12; 2064 GLsizei size = 0; 2065 const Str7 kString = {"foobar"}; 2066 char buf[20]; 2067 2068 ExpectedMemoryInfo mem1 = 2069 GetExpectedMemory(MaxTransferBufferSize()); 2070 ExpectedMemoryInfo result1 = 2071 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 2072 ExpectedMemoryInfo result2 = 2073 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2074 2075 memset(buf, kBad, sizeof(buf)); 2076 EXPECT_CALL(*command_buffer(), OnFlush()) 2077 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 2078 SetMemory(mem1.ptr, kString))) 2079 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 2080 .RetiresOnSaturation(); 2081 2082 struct Cmds { 2083 cmd::SetBucketSize set_bucket_size1; 2084 cmds::GetProgramInfoCHROMIUM get_program_info; 2085 cmd::GetBucketStart get_bucket_start; 2086 cmd::SetToken set_token1; 2087 cmd::SetBucketSize set_bucket_size2; 2088 }; 2089 Cmds expected; 2090 expected.set_bucket_size1.Init(kBucketId, 0); 2091 expected.get_program_info.Init(kProgramId, kBucketId); 2092 expected.get_bucket_start.Init( 2093 kBucketId, result1.id, result1.offset, 2094 MaxTransferBufferSize(), mem1.id, mem1.offset); 2095 expected.set_token1.Init(GetNextToken()); 2096 expected.set_bucket_size2.Init(kBucketId, 0); 2097 gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), &size, &buf); 2098 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2099 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 2100 EXPECT_EQ(sizeof(kString), static_cast<size_t>(size)); 2101 EXPECT_STREQ(kString.str, buf); 2102 EXPECT_EQ(buf[sizeof(kString)], kBad); 2103} 2104 2105TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) { 2106 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 2107 const GLuint kProgramId = 123; 2108 GLsizei size = 0; 2109 const Str7 kString = {"foobar"}; 2110 char buf[20]; 2111 2112 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 2113 ExpectedMemoryInfo result1 = 2114 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 2115 ExpectedMemoryInfo result2 = 2116 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2117 ExpectedMemoryInfo result3 = 2118 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2119 ExpectedMemoryInfo result4 = 2120 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2121 2122 EXPECT_CALL(*command_buffer(), OnFlush()) 2123 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 2124 SetMemory(mem1.ptr, kString))) 2125 .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR))) 2126 .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR))) 2127 .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR))) 2128 .RetiresOnSaturation(); 2129 2130 // try bufsize not big enough. 2131 struct Cmds { 2132 cmd::SetBucketSize set_bucket_size1; 2133 cmds::GetProgramInfoCHROMIUM get_program_info; 2134 cmd::GetBucketStart get_bucket_start; 2135 cmd::SetToken set_token1; 2136 cmd::SetBucketSize set_bucket_size2; 2137 }; 2138 Cmds expected; 2139 expected.set_bucket_size1.Init(kBucketId, 0); 2140 expected.get_program_info.Init(kProgramId, kBucketId); 2141 expected.get_bucket_start.Init( 2142 kBucketId, result1.id, result1.offset, 2143 MaxTransferBufferSize(), mem1.id, mem1.offset); 2144 expected.set_token1.Init(GetNextToken()); 2145 expected.set_bucket_size2.Init(kBucketId, 0); 2146 gl_->GetProgramInfoCHROMIUM(kProgramId, 6, &size, &buf); 2147 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2148 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError()); 2149 ClearCommands(); 2150 2151 // try bad bufsize 2152 gl_->GetProgramInfoCHROMIUM(kProgramId, -1, &size, &buf); 2153 EXPECT_TRUE(NoCommandsWritten()); 2154 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 2155 ClearCommands(); 2156 // try no size ptr. 2157 gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), NULL, &buf); 2158 EXPECT_TRUE(NoCommandsWritten()); 2159 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError()); 2160} 2161 2162// Test that things are cached 2163TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) { 2164 struct PNameValue { 2165 GLenum pname; 2166 GLint expected; 2167 }; 2168 const PNameValue pairs[] = { 2169 {GL_ACTIVE_TEXTURE, GL_TEXTURE0, }, 2170 {GL_TEXTURE_BINDING_2D, 0, }, 2171 {GL_TEXTURE_BINDING_CUBE_MAP, 0, }, 2172 {GL_TEXTURE_BINDING_EXTERNAL_OES, 0, }, 2173 {GL_FRAMEBUFFER_BINDING, 0, }, 2174 {GL_RENDERBUFFER_BINDING, 0, }, 2175 {GL_ARRAY_BUFFER_BINDING, 0, }, 2176 {GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, }, 2177 {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kMaxCombinedTextureImageUnits, }, 2178 {GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMaxCubeMapTextureSize, }, 2179 {GL_MAX_FRAGMENT_UNIFORM_VECTORS, kMaxFragmentUniformVectors, }, 2180 {GL_MAX_RENDERBUFFER_SIZE, kMaxRenderbufferSize, }, 2181 {GL_MAX_TEXTURE_IMAGE_UNITS, kMaxTextureImageUnits, }, 2182 {GL_MAX_TEXTURE_SIZE, kMaxTextureSize, }, 2183 {GL_MAX_VARYING_VECTORS, kMaxVaryingVectors, }, 2184 {GL_MAX_VERTEX_ATTRIBS, kMaxVertexAttribs, }, 2185 {GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMaxVertexTextureImageUnits, }, 2186 {GL_MAX_VERTEX_UNIFORM_VECTORS, kMaxVertexUniformVectors, }, 2187 {GL_NUM_COMPRESSED_TEXTURE_FORMATS, kNumCompressedTextureFormats, }, 2188 {GL_NUM_SHADER_BINARY_FORMATS, kNumShaderBinaryFormats, }, }; 2189 size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); 2190 for (size_t ii = 0; ii < num_pairs; ++ii) { 2191 const PNameValue& pv = pairs[ii]; 2192 GLint v = -1; 2193 gl_->GetIntegerv(pv.pname, &v); 2194 EXPECT_TRUE(NoCommandsWritten()); 2195 EXPECT_EQ(pv.expected, v); 2196 } 2197 2198 ExpectedMemoryInfo result1 = 2199 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2200 2201 EXPECT_CALL(*command_buffer(), OnFlush()) 2202 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 2203 .RetiresOnSaturation(); 2204 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 2205} 2206 2207TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) { 2208 struct PNameValue { 2209 GLenum pname; 2210 GLint expected; 2211 }; 2212 gl_->ActiveTexture(GL_TEXTURE4); 2213 gl_->BindBuffer(GL_ARRAY_BUFFER, 2); 2214 gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 3); 2215 gl_->BindFramebuffer(GL_FRAMEBUFFER, 4); 2216 gl_->BindRenderbuffer(GL_RENDERBUFFER, 5); 2217 gl_->BindTexture(GL_TEXTURE_2D, 6); 2218 gl_->BindTexture(GL_TEXTURE_CUBE_MAP, 7); 2219 gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, 8); 2220 2221 const PNameValue pairs[] = {{GL_ACTIVE_TEXTURE, GL_TEXTURE4, }, 2222 {GL_ARRAY_BUFFER_BINDING, 2, }, 2223 {GL_ELEMENT_ARRAY_BUFFER_BINDING, 3, }, 2224 {GL_FRAMEBUFFER_BINDING, 4, }, 2225 {GL_RENDERBUFFER_BINDING, 5, }, 2226 {GL_TEXTURE_BINDING_2D, 6, }, 2227 {GL_TEXTURE_BINDING_CUBE_MAP, 7, }, 2228 {GL_TEXTURE_BINDING_EXTERNAL_OES, 8, }, }; 2229 size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); 2230 for (size_t ii = 0; ii < num_pairs; ++ii) { 2231 const PNameValue& pv = pairs[ii]; 2232 GLint v = -1; 2233 gl_->GetIntegerv(pv.pname, &v); 2234 EXPECT_EQ(pv.expected, v); 2235 } 2236 2237 ExpectedMemoryInfo result1 = 2238 GetExpectedResultMemory(sizeof(cmds::GetError::Result)); 2239 2240 EXPECT_CALL(*command_buffer(), OnFlush()) 2241 .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR))) 2242 .RetiresOnSaturation(); 2243 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError()); 2244} 2245 2246static bool CheckRect( 2247 int width, int height, GLenum format, GLenum type, int alignment, 2248 bool flip_y, const uint8* r1, const uint8* r2) { 2249 uint32 size = 0; 2250 uint32 unpadded_row_size = 0; 2251 uint32 padded_row_size = 0; 2252 if (!GLES2Util::ComputeImageDataSizes( 2253 width, height, format, type, alignment, &size, &unpadded_row_size, 2254 &padded_row_size)) { 2255 return false; 2256 } 2257 2258 int r2_stride = flip_y ? 2259 -static_cast<int>(padded_row_size) : 2260 static_cast<int>(padded_row_size); 2261 r2 = flip_y ? (r2 + (height - 1) * padded_row_size) : r2; 2262 2263 for (int y = 0; y < height; ++y) { 2264 if (memcmp(r1, r2, unpadded_row_size) != 0) { 2265 return false; 2266 } 2267 r1 += padded_row_size; 2268 r2 += r2_stride; 2269 } 2270 return true; 2271} 2272 2273ACTION_P8(CheckRectAction, width, height, format, type, alignment, flip_y, 2274 r1, r2) { 2275 EXPECT_TRUE(CheckRect( 2276 width, height, format, type, alignment, flip_y, r1, r2)); 2277} 2278 2279// Test TexImage2D with and without flip_y 2280TEST_F(GLES2ImplementationTest, TexImage2D) { 2281 struct Cmds { 2282 cmds::TexImage2D tex_image_2d; 2283 cmd::SetToken set_token; 2284 }; 2285 struct Cmds2 { 2286 cmds::TexImage2D tex_image_2d; 2287 cmd::SetToken set_token; 2288 }; 2289 const GLenum kTarget = GL_TEXTURE_2D; 2290 const GLint kLevel = 0; 2291 const GLenum kFormat = GL_RGB; 2292 const GLsizei kWidth = 3; 2293 const GLsizei kHeight = 4; 2294 const GLint kBorder = 0; 2295 const GLenum kType = GL_UNSIGNED_BYTE; 2296 const GLint kPixelStoreUnpackAlignment = 4; 2297 static uint8 pixels[] = { 2298 11, 12, 13, 13, 14, 15, 15, 16, 17, 101, 102, 103, 2299 21, 22, 23, 23, 24, 25, 25, 26, 27, 201, 202, 203, 2300 31, 32, 33, 33, 34, 35, 35, 36, 37, 123, 124, 125, 2301 41, 42, 43, 43, 44, 45, 45, 46, 47, 2302 }; 2303 2304 ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels)); 2305 2306 Cmds expected; 2307 expected.tex_image_2d.Init( 2308 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2309 mem1.id, mem1.offset); 2310 expected.set_token.Init(GetNextToken()); 2311 gl_->TexImage2D( 2312 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2313 pixels); 2314 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2315 EXPECT_TRUE(CheckRect( 2316 kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false, 2317 pixels, mem1.ptr)); 2318 2319 ClearCommands(); 2320 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2321 2322 ExpectedMemoryInfo mem2 = GetExpectedMemory(sizeof(pixels)); 2323 Cmds2 expected2; 2324 expected2.tex_image_2d.Init( 2325 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2326 mem2.id, mem2.offset); 2327 expected2.set_token.Init(GetNextToken()); 2328 const void* commands2 = GetPut(); 2329 gl_->TexImage2D( 2330 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2331 pixels); 2332 EXPECT_EQ(0, memcmp(&expected2, commands2, sizeof(expected2))); 2333 EXPECT_TRUE(CheckRect( 2334 kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, true, 2335 pixels, mem2.ptr)); 2336} 2337 2338// Test TexImage2D with 2 writes 2339TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { 2340 struct Cmds { 2341 cmds::TexImage2D tex_image_2d; 2342 cmds::TexSubImage2D tex_sub_image_2d1; 2343 cmd::SetToken set_token1; 2344 cmds::TexSubImage2D tex_sub_image_2d2; 2345 cmd::SetToken set_token2; 2346 }; 2347 const GLenum kTarget = GL_TEXTURE_2D; 2348 const GLint kLevel = 0; 2349 const GLenum kFormat = GL_RGB; 2350 const GLint kBorder = 0; 2351 const GLenum kType = GL_UNSIGNED_BYTE; 2352 const GLint kPixelStoreUnpackAlignment = 4; 2353 const GLsizei kWidth = 3; 2354 2355 uint32 size = 0; 2356 uint32 unpadded_row_size = 0; 2357 uint32 padded_row_size = 0; 2358 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2359 kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, 2360 &size, &unpadded_row_size, &padded_row_size)); 2361 const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2; 2362 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2363 kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, 2364 &size, NULL, NULL)); 2365 uint32 half_size = 0; 2366 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2367 kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, 2368 &half_size, NULL, NULL)); 2369 2370 scoped_ptr<uint8[]> pixels(new uint8[size]); 2371 for (uint32 ii = 0; ii < size; ++ii) { 2372 pixels[ii] = static_cast<uint8>(ii); 2373 } 2374 2375 ExpectedMemoryInfo mem1 = GetExpectedMemory(half_size); 2376 ExpectedMemoryInfo mem2 = GetExpectedMemory(half_size); 2377 2378 Cmds expected; 2379 expected.tex_image_2d.Init( 2380 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2381 0, 0); 2382 expected.tex_sub_image_2d1.Init( 2383 kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, 2384 mem1.id, mem1.offset, true); 2385 expected.set_token1.Init(GetNextToken()); 2386 expected.tex_sub_image_2d2.Init( 2387 kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, 2388 mem2.id, mem2.offset, true); 2389 expected.set_token2.Init(GetNextToken()); 2390 2391 // TODO(gman): Make it possible to run this test 2392 // EXPECT_CALL(*command_buffer(), OnFlush()) 2393 // .WillOnce(CheckRectAction( 2394 // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, 2395 // false, pixels.get(), 2396 // GetExpectedTransferAddressFromOffsetAs<uint8>(offset1, half_size))) 2397 // .RetiresOnSaturation(); 2398 2399 gl_->TexImage2D( 2400 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2401 pixels.get()); 2402 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2403 EXPECT_TRUE(CheckRect( 2404 kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, false, 2405 pixels.get() + kHeight / 2 * padded_row_size, mem2.ptr)); 2406 2407 ClearCommands(); 2408 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2409 const void* commands2 = GetPut(); 2410 ExpectedMemoryInfo mem3 = GetExpectedMemory(half_size); 2411 ExpectedMemoryInfo mem4 = GetExpectedMemory(half_size); 2412 expected.tex_image_2d.Init( 2413 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2414 0, 0); 2415 expected.tex_sub_image_2d1.Init( 2416 kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, 2417 mem3.id, mem3.offset, true); 2418 expected.set_token1.Init(GetNextToken()); 2419 expected.tex_sub_image_2d2.Init( 2420 kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, 2421 mem4.id, mem4.offset, true); 2422 expected.set_token2.Init(GetNextToken()); 2423 2424 // TODO(gman): Make it possible to run this test 2425 // EXPECT_CALL(*command_buffer(), OnFlush()) 2426 // .WillOnce(CheckRectAction( 2427 // kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, 2428 // true, pixels.get(), 2429 // GetExpectedTransferAddressFromOffsetAs<uint8>(offset3, half_size))) 2430 // .RetiresOnSaturation(); 2431 2432 gl_->TexImage2D( 2433 kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, 2434 pixels.get()); 2435 EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected))); 2436 EXPECT_TRUE(CheckRect( 2437 kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, true, 2438 pixels.get() + kHeight / 2 * padded_row_size, mem4.ptr)); 2439} 2440 2441// Test TexSubImage2D with GL_PACK_FLIP_Y set and partial multirow transfers 2442TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) { 2443 const GLsizei kTextureWidth = MaxTransferBufferSize() / 4; 2444 const GLsizei kTextureHeight = 7; 2445 const GLsizei kSubImageWidth = MaxTransferBufferSize() / 8; 2446 const GLsizei kSubImageHeight = 4; 2447 const GLint kSubImageXOffset = 1; 2448 const GLint kSubImageYOffset = 2; 2449 const GLenum kFormat = GL_RGBA; 2450 const GLenum kType = GL_UNSIGNED_BYTE; 2451 const GLenum kTarget = GL_TEXTURE_2D; 2452 const GLint kLevel = 0; 2453 const GLint kBorder = 0; 2454 const GLint kPixelStoreUnpackAlignment = 4; 2455 2456 struct Cmds { 2457 cmds::PixelStorei pixel_store_i1; 2458 cmds::TexImage2D tex_image_2d; 2459 cmds::PixelStorei pixel_store_i2; 2460 cmds::TexSubImage2D tex_sub_image_2d1; 2461 cmd::SetToken set_token1; 2462 cmds::TexSubImage2D tex_sub_image_2d2; 2463 cmd::SetToken set_token2; 2464 }; 2465 2466 uint32 sub_2_high_size = 0; 2467 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2468 kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, 2469 &sub_2_high_size, NULL, NULL)); 2470 2471 ExpectedMemoryInfo mem1 = GetExpectedMemory(sub_2_high_size); 2472 ExpectedMemoryInfo mem2 = GetExpectedMemory(sub_2_high_size); 2473 2474 Cmds expected; 2475 expected.pixel_store_i1.Init(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment); 2476 expected.tex_image_2d.Init( 2477 kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat, 2478 kType, 0, 0); 2479 expected.pixel_store_i2.Init(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2480 expected.tex_sub_image_2d1.Init(kTarget, kLevel, kSubImageXOffset, 2481 kSubImageYOffset + 2, kSubImageWidth, 2, kFormat, kType, 2482 mem1.id, mem1.offset, false); 2483 expected.set_token1.Init(GetNextToken()); 2484 expected.tex_sub_image_2d2.Init(kTarget, kLevel, kSubImageXOffset, 2485 kSubImageYOffset, kSubImageWidth , 2, kFormat, kType, 2486 mem2.id, mem2.offset, false); 2487 expected.set_token2.Init(GetNextToken()); 2488 2489 gl_->PixelStorei(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment); 2490 gl_->TexImage2D( 2491 kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat, 2492 kType, NULL); 2493 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); 2494 scoped_ptr<uint32[]> pixels(new uint32[kSubImageWidth * kSubImageHeight]); 2495 for (int y = 0; y < kSubImageHeight; ++y) { 2496 for (int x = 0; x < kSubImageWidth; ++x) { 2497 pixels.get()[kSubImageWidth * y + x] = x | (y << 16); 2498 } 2499 } 2500 gl_->TexSubImage2D( 2501 GL_TEXTURE_2D, 0, kSubImageXOffset, kSubImageYOffset, kSubImageWidth, 2502 kSubImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); 2503 2504 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2505 EXPECT_TRUE(CheckRect( 2506 kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, true, 2507 reinterpret_cast<uint8*>(pixels.get() + 2 * kSubImageWidth), 2508 mem2.ptr)); 2509} 2510 2511TEST_F(GLES2ImplementationTest, SubImageUnpack) { 2512 static const GLint unpack_alignments[] = { 1, 2, 4, 8 }; 2513 2514 static const GLenum kFormat = GL_RGB; 2515 static const GLenum kType = GL_UNSIGNED_BYTE; 2516 static const GLint kLevel = 0; 2517 static const GLint kBorder = 0; 2518 // We're testing using the unpack params to pull a subimage out of a larger 2519 // source of pixels. Here we specify the subimage by its border rows / 2520 // columns. 2521 static const GLint kSrcWidth = 33; 2522 static const GLint kSrcSubImageX0 = 11; 2523 static const GLint kSrcSubImageX1 = 20; 2524 static const GLint kSrcSubImageY0 = 18; 2525 static const GLint kSrcSubImageY1 = 23; 2526 static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0; 2527 static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0; 2528 2529 // these are only used in the texsubimage tests 2530 static const GLint kTexWidth = 1023; 2531 static const GLint kTexHeight = 511; 2532 static const GLint kTexSubXOffset = 419; 2533 static const GLint kTexSubYOffset = 103; 2534 2535 struct { 2536 cmds::PixelStorei pixel_store_i; 2537 cmds::PixelStorei pixel_store_i2; 2538 cmds::TexImage2D tex_image_2d; 2539 } texImageExpected; 2540 2541 struct { 2542 cmds::PixelStorei pixel_store_i; 2543 cmds::PixelStorei pixel_store_i2; 2544 cmds::TexImage2D tex_image_2d; 2545 cmds::TexSubImage2D tex_sub_image_2d; 2546 } texSubImageExpected; 2547 2548 uint32 src_size; 2549 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2550 kSrcWidth, kSrcSubImageY1, kFormat, kType, 8, &src_size, NULL, NULL)); 2551 scoped_ptr<uint8[]> src_pixels; 2552 src_pixels.reset(new uint8[src_size]); 2553 for (size_t i = 0; i < src_size; ++i) { 2554 src_pixels[i] = static_cast<int8>(i); 2555 } 2556 2557 for (int sub = 0; sub < 2; ++sub) { 2558 for (int flip_y = 0; flip_y < 2; ++flip_y) { 2559 for (size_t a = 0; a < arraysize(unpack_alignments); ++a) { 2560 GLint alignment = unpack_alignments[a]; 2561 uint32 size; 2562 uint32 unpadded_row_size; 2563 uint32 padded_row_size; 2564 ASSERT_TRUE(GLES2Util::ComputeImageDataSizes( 2565 kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, alignment, 2566 &size, &unpadded_row_size, &padded_row_size)); 2567 ASSERT_TRUE(size <= MaxTransferBufferSize()); 2568 ExpectedMemoryInfo mem = GetExpectedMemory(size); 2569 2570 const void* commands = GetPut(); 2571 gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment); 2572 gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, kSrcWidth); 2573 gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, kSrcSubImageX0); 2574 gl_->PixelStorei(GL_UNPACK_SKIP_ROWS_EXT, kSrcSubImageY0); 2575 gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); 2576 if (sub) { 2577 gl_->TexImage2D( 2578 GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, 2579 kFormat, kType, NULL); 2580 gl_->TexSubImage2D( 2581 GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, 2582 kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, 2583 src_pixels.get()); 2584 texSubImageExpected.pixel_store_i.Init( 2585 GL_UNPACK_ALIGNMENT, alignment); 2586 texSubImageExpected.pixel_store_i2.Init( 2587 GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); 2588 texSubImageExpected.tex_image_2d.Init( 2589 GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder, 2590 kFormat, kType, 0, 0); 2591 texSubImageExpected.tex_sub_image_2d.Init( 2592 GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset, 2593 kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id, 2594 mem.offset, GL_FALSE); 2595 EXPECT_EQ(0, memcmp( 2596 &texSubImageExpected, commands, sizeof(texSubImageExpected))); 2597 } else { 2598 gl_->TexImage2D( 2599 GL_TEXTURE_2D, kLevel, kFormat, 2600 kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType, 2601 src_pixels.get()); 2602 texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment); 2603 texImageExpected.pixel_store_i2.Init( 2604 GL_UNPACK_FLIP_Y_CHROMIUM, flip_y); 2605 texImageExpected.tex_image_2d.Init( 2606 GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth, 2607 kSrcSubImageHeight, kBorder, kFormat, kType, mem.id, mem.offset); 2608 EXPECT_EQ(0, memcmp( 2609 &texImageExpected, commands, sizeof(texImageExpected))); 2610 } 2611 uint32 src_padded_row_size; 2612 ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize( 2613 kSrcWidth, kFormat, kType, alignment, &src_padded_row_size)); 2614 uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize( 2615 kFormat, kType); 2616 for (int y = 0; y < kSrcSubImageHeight; ++y) { 2617 GLint src_sub_y = flip_y ? kSrcSubImageHeight - y - 1 : y; 2618 const uint8* src_row = src_pixels.get() + 2619 (kSrcSubImageY0 + src_sub_y) * src_padded_row_size + 2620 bytes_per_group * kSrcSubImageX0; 2621 const uint8* dst_row = mem.ptr + y * padded_row_size; 2622 EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size)); 2623 } 2624 ClearCommands(); 2625 } 2626 } 2627 } 2628} 2629 2630// Binds can not be cached with bind_generates_resource = false because 2631// our id might not be valid. More specifically if you bind on contextA then 2632// delete on contextB the resource is still bound on contextA but GetInterger 2633// won't return an id. 2634TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) { 2635 struct PNameValue { 2636 GLenum pname; 2637 GLint expected; 2638 }; 2639 const PNameValue pairs[] = {{GL_TEXTURE_BINDING_2D, 1, }, 2640 {GL_TEXTURE_BINDING_CUBE_MAP, 2, }, 2641 {GL_TEXTURE_BINDING_EXTERNAL_OES, 3, }, 2642 {GL_FRAMEBUFFER_BINDING, 4, }, 2643 {GL_RENDERBUFFER_BINDING, 5, }, 2644 {GL_ARRAY_BUFFER_BINDING, 6, }, 2645 {GL_ELEMENT_ARRAY_BUFFER_BINDING, 7, }, }; 2646 size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); 2647 for (size_t ii = 0; ii < num_pairs; ++ii) { 2648 const PNameValue& pv = pairs[ii]; 2649 GLint v = -1; 2650 ExpectedMemoryInfo result1 = 2651 GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result)); 2652 EXPECT_CALL(*command_buffer(), OnFlush()) 2653 .WillOnce(SetMemory(result1.ptr, 2654 SizedResultHelper<GLuint>(pv.expected))) 2655 .RetiresOnSaturation(); 2656 gl_->GetIntegerv(pv.pname, &v); 2657 EXPECT_EQ(pv.expected, v); 2658 } 2659} 2660 2661// glGen* Ids must not be reused until glDelete* commands have been 2662// flushed by glFlush. 2663TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestBuffers) { 2664 FlushGenerationTest<GenBuffersAPI>(); 2665} 2666TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestFramebuffers) { 2667 FlushGenerationTest<GenFramebuffersAPI>(); 2668} 2669TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestRenderbuffers) { 2670 FlushGenerationTest<GenRenderbuffersAPI>(); 2671} 2672TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestTextures) { 2673 FlushGenerationTest<GenTexturesAPI>(); 2674} 2675 2676// glGen* Ids must not be reused cross-context until glDelete* commands are 2677// flushed by glFlush, and the Ids are lazily freed after. 2678TEST_F(GLES2ImplementationStrictSharedTest, CrossContextGenerationTestBuffers) { 2679 CrossContextGenerationTest<GenBuffersAPI>(); 2680} 2681TEST_F(GLES2ImplementationStrictSharedTest, 2682 CrossContextGenerationTestFramebuffers) { 2683 CrossContextGenerationTest<GenFramebuffersAPI>(); 2684} 2685TEST_F(GLES2ImplementationStrictSharedTest, 2686 CrossContextGenerationTestRenderbuffers) { 2687 CrossContextGenerationTest<GenRenderbuffersAPI>(); 2688} 2689TEST_F(GLES2ImplementationStrictSharedTest, 2690 CrossContextGenerationTestTextures) { 2691 CrossContextGenerationTest<GenTexturesAPI>(); 2692} 2693 2694// Test Delete which causes auto flush. Tests a regression case that occurred 2695// in testing. 2696TEST_F(GLES2ImplementationStrictSharedTest, 2697 CrossContextGenerationAutoFlushTestBuffers) { 2698 CrossContextGenerationAutoFlushTest<GenBuffersAPI>(); 2699} 2700TEST_F(GLES2ImplementationStrictSharedTest, 2701 CrossContextGenerationAutoFlushTestFramebuffers) { 2702 CrossContextGenerationAutoFlushTest<GenFramebuffersAPI>(); 2703} 2704TEST_F(GLES2ImplementationStrictSharedTest, 2705 CrossContextGenerationAutoFlushTestRenderbuffers) { 2706 CrossContextGenerationAutoFlushTest<GenRenderbuffersAPI>(); 2707} 2708TEST_F(GLES2ImplementationStrictSharedTest, 2709 CrossContextGenerationAutoFlushTestTextures) { 2710 CrossContextGenerationAutoFlushTest<GenTexturesAPI>(); 2711} 2712 2713TEST_F(GLES2ImplementationTest, GetString) { 2714 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 2715 const Str7 kString = {"foobar"}; 2716 // GL_CHROMIUM_map_sub GL_CHROMIUM_flipy are hard coded into 2717 // GLES2Implementation. 2718 const char* expected_str = 2719 "foobar " 2720 "GL_CHROMIUM_flipy " 2721 "GL_EXT_unpack_subimage"; 2722 const char kBad = 0x12; 2723 struct Cmds { 2724 cmd::SetBucketSize set_bucket_size1; 2725 cmds::GetString get_string; 2726 cmd::GetBucketStart get_bucket_start; 2727 cmd::SetToken set_token1; 2728 cmd::SetBucketSize set_bucket_size2; 2729 }; 2730 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 2731 ExpectedMemoryInfo result1 = 2732 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 2733 Cmds expected; 2734 expected.set_bucket_size1.Init(kBucketId, 0); 2735 expected.get_string.Init(GL_EXTENSIONS, kBucketId); 2736 expected.get_bucket_start.Init( 2737 kBucketId, result1.id, result1.offset, 2738 MaxTransferBufferSize(), mem1.id, mem1.offset); 2739 expected.set_token1.Init(GetNextToken()); 2740 expected.set_bucket_size2.Init(kBucketId, 0); 2741 char buf[sizeof(kString) + 1]; 2742 memset(buf, kBad, sizeof(buf)); 2743 2744 EXPECT_CALL(*command_buffer(), OnFlush()) 2745 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 2746 SetMemory(mem1.ptr, kString))) 2747 .RetiresOnSaturation(); 2748 2749 const GLubyte* result = gl_->GetString(GL_EXTENSIONS); 2750 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2751 EXPECT_STREQ(expected_str, reinterpret_cast<const char*>(result)); 2752} 2753 2754TEST_F(GLES2ImplementationTest, PixelStoreiGLPackReverseRowOrderANGLE) { 2755 const uint32 kBucketId = GLES2Implementation::kResultBucketId; 2756 const Str7 kString = {"foobar"}; 2757 struct Cmds { 2758 cmd::SetBucketSize set_bucket_size1; 2759 cmds::GetString get_string; 2760 cmd::GetBucketStart get_bucket_start; 2761 cmd::SetToken set_token1; 2762 cmd::SetBucketSize set_bucket_size2; 2763 cmds::PixelStorei pixel_store; 2764 }; 2765 2766 ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize()); 2767 ExpectedMemoryInfo result1 = 2768 GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result)); 2769 2770 Cmds expected; 2771 expected.set_bucket_size1.Init(kBucketId, 0); 2772 expected.get_string.Init(GL_EXTENSIONS, kBucketId); 2773 expected.get_bucket_start.Init( 2774 kBucketId, result1.id, result1.offset, 2775 MaxTransferBufferSize(), mem1.id, mem1.offset); 2776 expected.set_token1.Init(GetNextToken()); 2777 expected.set_bucket_size2.Init(kBucketId, 0); 2778 expected.pixel_store.Init(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1); 2779 2780 EXPECT_CALL(*command_buffer(), OnFlush()) 2781 .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))), 2782 SetMemory(mem1.ptr, kString))) 2783 .RetiresOnSaturation(); 2784 2785 gl_->PixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1); 2786 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2787} 2788 2789TEST_F(GLES2ImplementationTest, CreateProgram) { 2790 struct Cmds { 2791 cmds::CreateProgram cmd; 2792 }; 2793 2794 Cmds expected; 2795 expected.cmd.Init(kProgramsAndShadersStartId); 2796 GLuint id = gl_->CreateProgram(); 2797 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2798 EXPECT_EQ(kProgramsAndShadersStartId, id); 2799} 2800 2801TEST_F(GLES2ImplementationTest, BufferDataLargerThanTransferBuffer) { 2802 struct Cmds { 2803 cmds::BufferData set_size; 2804 cmds::BufferSubData copy_data1; 2805 cmd::SetToken set_token1; 2806 cmds::BufferSubData copy_data2; 2807 cmd::SetToken set_token2; 2808 }; 2809 const unsigned kUsableSize = 2810 kTransferBufferSize - GLES2Implementation::kStartingOffset; 2811 uint8 buf[kUsableSize * 2] = { 0, }; 2812 2813 ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize); 2814 ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize); 2815 2816 Cmds expected; 2817 expected.set_size.Init( 2818 GL_ARRAY_BUFFER, arraysize(buf), 0, 0, GL_DYNAMIC_DRAW); 2819 expected.copy_data1.Init( 2820 GL_ARRAY_BUFFER, 0, kUsableSize, mem1.id, mem1.offset); 2821 expected.set_token1.Init(GetNextToken()); 2822 expected.copy_data2.Init( 2823 GL_ARRAY_BUFFER, kUsableSize, kUsableSize, mem2.id, mem2.offset); 2824 expected.set_token2.Init(GetNextToken()); 2825 gl_->BufferData(GL_ARRAY_BUFFER, arraysize(buf), buf, GL_DYNAMIC_DRAW); 2826 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 2827} 2828 2829TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) { 2830 static const GLenum kStates[] = { 2831 GL_DITHER, 2832 GL_BLEND, 2833 GL_CULL_FACE, 2834 GL_DEPTH_TEST, 2835 GL_POLYGON_OFFSET_FILL, 2836 GL_SAMPLE_ALPHA_TO_COVERAGE, 2837 GL_SAMPLE_COVERAGE, 2838 GL_SCISSOR_TEST, 2839 GL_STENCIL_TEST, 2840 }; 2841 struct Cmds { 2842 cmds::Enable enable_cmd; 2843 }; 2844 Cmds expected; 2845 2846 for (size_t ii = 0; ii < arraysize(kStates); ++ii) { 2847 GLenum state = kStates[ii]; 2848 expected.enable_cmd.Init(state); 2849 GLboolean result = gl_->IsEnabled(state); 2850 EXPECT_EQ(static_cast<GLboolean>(ii == 0), result); 2851 EXPECT_TRUE(NoCommandsWritten()); 2852 const void* commands = GetPut(); 2853 if (!result) { 2854 gl_->Enable(state); 2855 EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected))); 2856 } 2857 ClearCommands(); 2858 result = gl_->IsEnabled(state); 2859 EXPECT_TRUE(result); 2860 EXPECT_TRUE(NoCommandsWritten()); 2861 } 2862} 2863 2864TEST_F(GLES2ImplementationTest, BindVertexArrayOES) { 2865 GLuint id = 0; 2866 gl_->GenVertexArraysOES(1, &id); 2867 ClearCommands(); 2868 2869 struct Cmds { 2870 cmds::BindVertexArrayOES cmd; 2871 }; 2872 Cmds expected; 2873 expected.cmd.Init(id); 2874 2875 const void* commands = GetPut(); 2876 gl_->BindVertexArrayOES(id); 2877 EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected))); 2878 ClearCommands(); 2879 gl_->BindVertexArrayOES(id); 2880 EXPECT_TRUE(NoCommandsWritten()); 2881} 2882 2883TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) { 2884 // Test GetQueryivEXT returns 0 if no current query. 2885 GLint param = -1; 2886 gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, ¶m); 2887 EXPECT_EQ(0, param); 2888 2889 GLuint expected_ids[2] = { 1, 2 }; // These must match what's actually genned. 2890 struct GenCmds { 2891 cmds::GenQueriesEXTImmediate gen; 2892 GLuint data[2]; 2893 }; 2894 GenCmds expected_gen_cmds; 2895 expected_gen_cmds.gen.Init(arraysize(expected_ids), &expected_ids[0]); 2896 GLuint ids[arraysize(expected_ids)] = { 0, }; 2897 gl_->GenQueriesEXT(arraysize(expected_ids), &ids[0]); 2898 EXPECT_EQ(0, memcmp( 2899 &expected_gen_cmds, commands_, sizeof(expected_gen_cmds))); 2900 GLuint id1 = ids[0]; 2901 GLuint id2 = ids[1]; 2902 ClearCommands(); 2903 2904 // Test BeginQueryEXT fails if id = 0. 2905 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0); 2906 EXPECT_TRUE(NoCommandsWritten()); 2907 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2908 2909 // Test BeginQueryEXT fails if id not GENed. 2910 // TODO(gman): 2911 2912 // Test BeginQueryEXT inserts command. 2913 struct BeginCmds { 2914 cmds::BeginQueryEXT begin_query; 2915 }; 2916 BeginCmds expected_begin_cmds; 2917 const void* commands = GetPut(); 2918 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1); 2919 QueryTracker::Query* query = GetQuery(id1); 2920 ASSERT_TRUE(query != NULL); 2921 expected_begin_cmds.begin_query.Init( 2922 GL_ANY_SAMPLES_PASSED_EXT, id1, query->shm_id(), query->shm_offset()); 2923 EXPECT_EQ(0, memcmp( 2924 &expected_begin_cmds, commands, sizeof(expected_begin_cmds))); 2925 ClearCommands(); 2926 2927 // Test GetQueryivEXT returns id. 2928 param = -1; 2929 gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, ¶m); 2930 EXPECT_EQ(id1, static_cast<GLuint>(param)); 2931 gl_->GetQueryivEXT( 2932 GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_CURRENT_QUERY_EXT, ¶m); 2933 EXPECT_EQ(0, param); 2934 2935 // Test BeginQueryEXT fails if between Begin/End. 2936 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id2); 2937 EXPECT_TRUE(NoCommandsWritten()); 2938 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2939 2940 // Test EndQueryEXT fails if target not same as current query. 2941 ClearCommands(); 2942 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); 2943 EXPECT_TRUE(NoCommandsWritten()); 2944 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2945 2946 // Test EndQueryEXT sends command 2947 struct EndCmds { 2948 cmds::EndQueryEXT end_query; 2949 }; 2950 EndCmds expected_end_cmds; 2951 expected_end_cmds.end_query.Init( 2952 GL_ANY_SAMPLES_PASSED_EXT, query->submit_count()); 2953 commands = GetPut(); 2954 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 2955 EXPECT_EQ(0, memcmp( 2956 &expected_end_cmds, commands, sizeof(expected_end_cmds))); 2957 2958 // Test EndQueryEXT fails if no current query. 2959 ClearCommands(); 2960 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 2961 EXPECT_TRUE(NoCommandsWritten()); 2962 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2963 2964 // Test 2nd Begin/End increments count. 2965 base::subtle::Atomic32 old_submit_count = query->submit_count(); 2966 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1); 2967 EXPECT_NE(old_submit_count, query->submit_count()); 2968 expected_end_cmds.end_query.Init( 2969 GL_ANY_SAMPLES_PASSED_EXT, query->submit_count()); 2970 commands = GetPut(); 2971 gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); 2972 EXPECT_EQ(0, memcmp( 2973 &expected_end_cmds, commands, sizeof(expected_end_cmds))); 2974 2975 // Test BeginQueryEXT fails if target changed. 2976 ClearCommands(); 2977 gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, id1); 2978 EXPECT_TRUE(NoCommandsWritten()); 2979 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2980 2981 // Test GetQueryObjectuivEXT fails if unused id 2982 GLuint available = 0xBDu; 2983 ClearCommands(); 2984 gl_->GetQueryObjectuivEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2985 EXPECT_TRUE(NoCommandsWritten()); 2986 EXPECT_EQ(0xBDu, available); 2987 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2988 2989 // Test GetQueryObjectuivEXT fails if bad id 2990 ClearCommands(); 2991 gl_->GetQueryObjectuivEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2992 EXPECT_TRUE(NoCommandsWritten()); 2993 EXPECT_EQ(0xBDu, available); 2994 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 2995 2996 // Test GetQueryObjectuivEXT CheckResultsAvailable 2997 ClearCommands(); 2998 gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 2999 EXPECT_TRUE(NoCommandsWritten()); 3000 EXPECT_EQ(0u, available); 3001} 3002 3003TEST_F(GLES2ImplementationTest, ErrorQuery) { 3004 GLuint id = 0; 3005 gl_->GenQueriesEXT(1, &id); 3006 ClearCommands(); 3007 3008 // Test BeginQueryEXT does NOT insert commands. 3009 gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id); 3010 EXPECT_TRUE(NoCommandsWritten()); 3011 QueryTracker::Query* query = GetQuery(id); 3012 ASSERT_TRUE(query != NULL); 3013 3014 // Test EndQueryEXT sends both begin and end command 3015 struct EndCmds { 3016 cmds::BeginQueryEXT begin_query; 3017 cmds::EndQueryEXT end_query; 3018 }; 3019 EndCmds expected_end_cmds; 3020 expected_end_cmds.begin_query.Init( 3021 GL_GET_ERROR_QUERY_CHROMIUM, id, query->shm_id(), query->shm_offset()); 3022 expected_end_cmds.end_query.Init( 3023 GL_GET_ERROR_QUERY_CHROMIUM, query->submit_count()); 3024 const void* commands = GetPut(); 3025 gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); 3026 EXPECT_EQ(0, memcmp( 3027 &expected_end_cmds, commands, sizeof(expected_end_cmds))); 3028 ClearCommands(); 3029 3030 // Check result is not yet available. 3031 GLuint available = 0xBDu; 3032 gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 3033 EXPECT_TRUE(NoCommandsWritten()); 3034 EXPECT_EQ(0u, available); 3035 3036 // Test no commands are sent if there is a client side error. 3037 3038 // Generate a client side error 3039 gl_->ActiveTexture(GL_TEXTURE0 - 1); 3040 3041 gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id); 3042 gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); 3043 EXPECT_TRUE(NoCommandsWritten()); 3044 3045 // Check result is available. 3046 gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available); 3047 EXPECT_TRUE(NoCommandsWritten()); 3048 EXPECT_NE(0u, available); 3049 3050 // Check result. 3051 GLuint result = 0xBDu; 3052 gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_EXT, &result); 3053 EXPECT_TRUE(NoCommandsWritten()); 3054 EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), result); 3055} 3056 3057#if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) 3058TEST_F(GLES2ImplementationTest, VertexArrays) { 3059 const GLuint kAttribIndex1 = 1; 3060 const GLint kNumComponents1 = 3; 3061 const GLsizei kClientStride = 12; 3062 3063 GLuint id = 0; 3064 gl_->GenVertexArraysOES(1, &id); 3065 ClearCommands(); 3066 3067 gl_->BindVertexArrayOES(id); 3068 3069 // Test that VertexAttribPointer cannot be called with a bound buffer of 0 3070 // unless the offset is NULL 3071 gl_->BindBuffer(GL_ARRAY_BUFFER, 0); 3072 3073 gl_->VertexAttribPointer( 3074 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, 3075 reinterpret_cast<const void*>(4)); 3076 EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); 3077 3078 gl_->VertexAttribPointer( 3079 kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, NULL); 3080 EXPECT_EQ(GL_NO_ERROR, CheckError()); 3081} 3082#endif 3083 3084TEST_F(GLES2ImplementationTest, Disable) { 3085 struct Cmds { 3086 cmds::Disable cmd; 3087 }; 3088 Cmds expected; 3089 expected.cmd.Init(GL_DITHER); // Note: DITHER defaults to enabled. 3090 3091 gl_->Disable(GL_DITHER); 3092 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 3093 // Check it's cached and not called again. 3094 ClearCommands(); 3095 gl_->Disable(GL_DITHER); 3096 EXPECT_TRUE(NoCommandsWritten()); 3097} 3098 3099TEST_F(GLES2ImplementationTest, Enable) { 3100 struct Cmds { 3101 cmds::Enable cmd; 3102 }; 3103 Cmds expected; 3104 expected.cmd.Init(GL_BLEND); // Note: BLEND defaults to disabled. 3105 3106 gl_->Enable(GL_BLEND); 3107 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 3108 // Check it's cached and not called again. 3109 ClearCommands(); 3110 gl_->Enable(GL_BLEND); 3111 EXPECT_TRUE(NoCommandsWritten()); 3112} 3113 3114TEST_F(GLES2ImplementationTest, ConsumeTextureCHROMIUM) { 3115 struct Cmds { 3116 cmds::ConsumeTextureCHROMIUMImmediate cmd; 3117 GLbyte data[64]; 3118 }; 3119 3120 Mailbox mailbox = Mailbox::Generate(); 3121 Cmds expected; 3122 expected.cmd.Init(GL_TEXTURE_2D, mailbox.name); 3123 gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 3124 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 3125} 3126 3127TEST_F(GLES2ImplementationTest, ProduceTextureCHROMIUM) { 3128 struct Cmds { 3129 cmds::ProduceTextureCHROMIUMImmediate cmd; 3130 GLbyte data[64]; 3131 }; 3132 3133 Mailbox mailbox = Mailbox::Generate(); 3134 Cmds expected; 3135 expected.cmd.Init(GL_TEXTURE_2D, mailbox.name); 3136 gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 3137 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 3138} 3139 3140TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) { 3141 ContextInitOptions init_options; 3142 init_options.lose_context_when_out_of_memory = true; 3143 ASSERT_TRUE(Initialize(init_options)); 3144 3145 struct Cmds { 3146 cmds::LoseContextCHROMIUM cmd; 3147 }; 3148 3149 GLsizei max = std::numeric_limits<GLsizei>::max(); 3150 EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _)) 3151 .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL))); 3152 gl_->CreateImageCHROMIUM(max, max, 0); 3153 // The context should be lost. 3154 Cmds expected; 3155 expected.cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_UNKNOWN_CONTEXT_RESET_ARB); 3156 EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); 3157} 3158 3159TEST_F(GLES2ImplementationManualInitTest, NoLoseContextOnOOM) { 3160 ContextInitOptions init_options; 3161 ASSERT_TRUE(Initialize(init_options)); 3162 3163 struct Cmds { 3164 cmds::LoseContextCHROMIUM cmd; 3165 }; 3166 3167 GLsizei max = std::numeric_limits<GLsizei>::max(); 3168 EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _)) 3169 .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL))); 3170 gl_->CreateImageCHROMIUM(max, max, 0); 3171 // The context should not be lost. 3172 EXPECT_TRUE(NoCommandsWritten()); 3173} 3174 3175TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch1) { 3176 ContextInitOptions init_options; 3177 init_options.bind_generates_resource_client = false; 3178 init_options.bind_generates_resource_service = true; 3179 EXPECT_FALSE(Initialize(init_options)); 3180} 3181 3182TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch2) { 3183 ContextInitOptions init_options; 3184 init_options.bind_generates_resource_client = true; 3185 init_options.bind_generates_resource_service = false; 3186 EXPECT_FALSE(Initialize(init_options)); 3187} 3188 3189#include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h" 3190 3191} // namespace gles2 3192} // namespace gpu 3193