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