diff options
Diffstat (limited to 'gpu/command_buffer/client/gles2_implementation_unittest.cc')
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 677 |
1 files changed, 677 insertions, 0 deletions
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc new file mode 100644 index 0000000..79cf95e --- /dev/null +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -0,0 +1,677 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Tests for the Command Buffer Helper. + +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/common/command_buffer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace gpu { + +class GLES2MockCommandBufferHelper : public CommandBuffer { + public: + static const int32 kTransferBufferId = 0x123; + + GLES2MockCommandBufferHelper() { } + virtual ~GLES2MockCommandBufferHelper() { } + + // CommandBuffer implementation: + virtual bool Initialize(int32 size) { + ring_buffer_.reset(new CommandBufferEntry[size]); + ring_buffer_buffer_.ptr = ring_buffer_.get(); + ring_buffer_buffer_.size = size * sizeof(ring_buffer_[0]); + state_.size = size; + state_.token = 10000; // All token checks in the tests should pass. + return true; + } + + virtual Buffer GetRingBuffer() { + return ring_buffer_buffer_; + } + + virtual State GetState() { + return state_; + } + + virtual State Flush(int32 put_offset) { + state_.put_offset = put_offset; + state_.get_offset = put_offset; + OnFlush(transfer_buffer_buffer_.ptr); + + return state_; + } + + virtual void SetGetOffset(int32 get_offset) { + state_.get_offset = get_offset; + } + + virtual int32 CreateTransferBuffer(size_t size) { + transfer_buffer_.reset(new int8[size]); + transfer_buffer_buffer_.ptr = transfer_buffer_.get(); + transfer_buffer_buffer_.size = size; + return kTransferBufferId; + } + + virtual void DestroyTransferBuffer(int32) { // NOLINT + NOTREACHED(); + } + + virtual Buffer GetTransferBuffer(int32 id) { + DCHECK_EQ(id, kTransferBufferId); + return transfer_buffer_buffer_; + } + + virtual void SetToken(int32 token) { + NOTREACHED(); + state_.token = token; + } + + virtual void SetParseError(error::Error error) { + NOTREACHED(); + state_.error = error; + } + + virtual void OnFlush(void* transfer_buffer) = 0; + + private: + scoped_array<int8> transfer_buffer_; + Buffer transfer_buffer_buffer_; + scoped_array<CommandBufferEntry> ring_buffer_; + Buffer ring_buffer_buffer_; + State state_; +}; + +class MockGLES2CommandBuffer : public GLES2MockCommandBufferHelper { + public: + virtual ~MockGLES2CommandBuffer() { + } + + // This is so we can use all the gmock functions when Flush is called. + MOCK_METHOD1(OnFlush, void(void* result)); +}; + +namespace gles2 { + +using testing::Return; +using testing::Mock; +using testing::Truly; +using testing::Sequence; +using testing::DoAll; +using testing::Invoke; +using testing::_; + +ACTION_P(SetMemory, obj) { + memcpy(arg0, &obj, sizeof(obj)); +} + +// Used to help set the transfer buffer result to SizedResult of a single value. +template <typename T> +class SizedResultHelper { + public: + explicit SizedResultHelper(T result) + : size_(sizeof(result)), + result_(result) { + } + + private: + uint32 size_; + T result_; +}; + +// Struct to make it easy to pass a vec4 worth of floats. +struct FourFloats { + FourFloats(float _x, float _y, float _z, float _w) + : x(_x), + y(_y), + z(_z), + w(_w) { + } + + float x; + float y; + float z; + float w; +}; + +// Test fixture for CommandBufferHelper test. +class GLES2ImplementationTest : public testing::Test { + protected: + static const int32 kNumCommandEntries = 100; + static const int32 kCommandBufferSizeBytes = + kNumCommandEntries * sizeof(CommandBufferEntry); + static const size_t kTransferBufferSize = 256; + static const int32 kTransferBufferId = + GLES2MockCommandBufferHelper::kTransferBufferId; + static const uint8 kInitialValue = 0xBD; + static const GLint kMaxVertexAttribs = 8; + + virtual void SetUp() { + command_buffer_.reset(new MockGLES2CommandBuffer()); + command_buffer_->Initialize(kNumCommandEntries); + + + EXPECT_EQ(kTransferBufferId, + command_buffer_->CreateTransferBuffer(kTransferBufferSize)); + transfer_buffer_ = command_buffer_->GetTransferBuffer(kTransferBufferId); + ClearTransferBuffer(); + + helper_.reset(new GLES2CmdHelper(command_buffer_.get())); + helper_->Initialize(); + + #if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS) + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(SizedResultHelper<GLint>(kMaxVertexAttribs))) + .RetiresOnSaturation(); + #endif + + gl_.reset(new GLES2Implementation( + helper_.get(), + kTransferBufferSize, + transfer_buffer_.ptr, + kTransferBufferId)); + + EXPECT_CALL(*command_buffer_, OnFlush(_)).Times(1).RetiresOnSaturation(); + helper_->CommandBufferHelper::Flush(); + Buffer ring_buffer = command_buffer_->GetRingBuffer(); + commands_ = static_cast<CommandBufferEntry*>(ring_buffer.ptr) + + command_buffer_->GetState().put_offset; + } + + virtual void TearDown() { + } + + void ClearTransferBuffer() { + memset(transfer_buffer_.ptr, kInitialValue, kTransferBufferSize); + } + + static unsigned int RoundToAlignment(unsigned int size) { + return (size + GLES2Implementation::kAlignment - 1) & + ~(GLES2Implementation::kAlignment - 1); + } + + Buffer transfer_buffer_; + CommandBufferEntry* commands_; + scoped_ptr<MockGLES2CommandBuffer> command_buffer_; + scoped_ptr<GLES2CmdHelper> helper_; + Sequence sequence_; + scoped_ptr<GLES2Implementation> gl_; +}; + +// GCC requires these declarations, but MSVC requires they not be present +#ifndef COMPILER_MSVC +const int32 GLES2ImplementationTest::kTransferBufferId; +#endif + + +TEST_F(GLES2ImplementationTest, ShaderSource) { + const uint32 kBucketId = 1; // This id is hardcoded into GLES2Implemenation + const GLuint kShaderId = 456; + const char* kString1 = "foobar"; + const char* kString2 = "barfoo"; + const size_t kString1Size = strlen(kString1); + const size_t kString2Size = strlen(kString2); + const size_t kString3Size = 1; // Want the NULL; + const size_t kSourceSize = kString1Size + kString2Size + kString3Size; + const size_t kPaddedString1Size = RoundToAlignment(kString1Size); + const size_t kPaddedString2Size = RoundToAlignment(kString2Size); + struct Cmds { + cmd::SetBucketSize set_bucket_size; + cmd::SetBucketData set_bucket_data1; + cmd::SetToken set_token1; + cmd::SetBucketData set_bucket_data2; + cmd::SetToken set_token2; + cmd::SetBucketData set_bucket_data3; + cmd::SetToken set_token3; + ShaderSourceBucket shader_source_bucket; + cmd::SetBucketSize clear_bucket_size; + }; + int32 token = 1; + uint32 offset = GLES2Implementation::kStartingOffset; + Cmds expected; + expected.set_bucket_size.Init(kBucketId, kSourceSize); + expected.set_bucket_data1.Init( + kBucketId, 0, kString1Size, kTransferBufferId, offset); + expected.set_token1.Init(token++); + expected.set_bucket_data2.Init( + kBucketId, kString1Size, kString2Size, kTransferBufferId, + offset + kPaddedString1Size); + expected.set_token2.Init(token++); + expected.set_bucket_data3.Init( + kBucketId, kString1Size + kString2Size, + kString3Size, kTransferBufferId, + offset + kPaddedString1Size + kPaddedString2Size); + expected.set_token3.Init(token++); + expected.shader_source_bucket.Init(kShaderId, kBucketId); + expected.clear_bucket_size.Init(kBucketId, 0); + const char* strings[] = { + kString1, + kString2, + }; + gl_->ShaderSource(kShaderId, 2, strings, NULL); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +#if defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS) + +TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) { + static const float verts[][4] = { + { 12.0f, 23.0f, 34.0f, 45.0f, }, + { 56.0f, 67.0f, 78.0f, 89.0f, }, + { 13.0f, 24.0f, 35.0f, 46.0f, }, + }; + struct Cmds { + EnableVertexAttribArray enable1; + EnableVertexAttribArray enable2; + BindBuffer bind_to_emu; + BufferData set_size; + BufferSubData copy_data1; + cmd::SetToken set_token1; + VertexAttribPointer set_pointer1; + BufferSubData copy_data2; + cmd::SetToken set_token2; + VertexAttribPointer set_pointer2; + DrawArrays draw; + BindBuffer restore; + }; + const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kClientStride = sizeof(verts[0]); + const GLint kFirst = 1; + const GLsizei kCount = 2; + const GLsizei kSize1 = + arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); + const GLsizei kSize2 = + arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); + const GLsizei kEmuOffset1 = 0; + const GLsizei kEmuOffset2 = kSize1; + + const GLsizei kTotalSize = kSize1 + kSize2; + int32 token = 1; + uint32 offset = GLES2Implementation::kStartingOffset; + Cmds expected; + expected.enable1.Init(kAttribIndex1); + expected.enable2.Init(kAttribIndex2); + expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); + expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); + expected.copy_data1.Init( + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, kTransferBufferId, offset); + expected.set_token1.Init(token++); + expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, 0, kEmuOffset1); + expected.copy_data2.Init( + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, kTransferBufferId, offset + kSize1); + expected.set_token2.Init(token++); + expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, 0, kEmuOffset2); + expected.draw.Init(GL_POINTS, kFirst, kCount); + expected.restore.Init(GL_ARRAY_BUFFER, 0); + gl_->EnableVertexAttribArray(kAttribIndex1); + gl_->EnableVertexAttribArray(kAttribIndex2); + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->DrawArrays(GL_POINTS, kFirst, kCount); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) { + static const float verts[][4] = { + { 12.0f, 23.0f, 34.0f, 45.0f, }, + { 56.0f, 67.0f, 78.0f, 89.0f, }, + { 13.0f, 24.0f, 35.0f, 46.0f, }, + }; + static const uint16 indices[] = { + 1, 2, + }; + struct Cmds { + EnableVertexAttribArray enable1; + EnableVertexAttribArray enable2; + BindBuffer bind_to_index_emu; + BufferData set_index_size; + BufferSubData copy_data0; + cmd::SetToken set_token0; + BindBuffer bind_to_emu; + BufferData set_size; + BufferSubData copy_data1; + cmd::SetToken set_token1; + VertexAttribPointer set_pointer1; + BufferSubData copy_data2; + cmd::SetToken set_token2; + VertexAttribPointer set_pointer2; + DrawElements draw; + BindBuffer restore; + BindBuffer restore_element; + }; + const GLsizei kIndexSize = sizeof(indices); + const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; + const GLuint kEmuIndexBufferId = + GLES2Implementation::kClientSideElementArrayId; + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kClientStride = sizeof(verts[0]); + const GLsizei kCount = 2; + const GLsizei kSize1 = + arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); + const GLsizei kSize2 = + arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); + const GLsizei kEmuOffset1 = 0; + const GLsizei kEmuOffset2 = kSize1; + + const GLsizei kTotalSize = kSize1 + kSize2; + int32 token = 1; + uint32 offset = GLES2Implementation::kStartingOffset; + Cmds expected; + expected.enable1.Init(kAttribIndex1); + expected.enable2.Init(kAttribIndex2); + expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId); + expected.set_index_size.Init( + GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); + expected.copy_data0.Init( + GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, kTransferBufferId, offset); + offset += kIndexSize; + expected.set_token0.Init(token++); + expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); + expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); + expected.copy_data1.Init( + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, kTransferBufferId, offset); + offset += kSize1; + expected.set_token1.Init(token++); + expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, 0, kEmuOffset1); + expected.copy_data2.Init( + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, kTransferBufferId, offset); + expected.set_token2.Init(token++); + expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, 0, kEmuOffset2); + expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0); + expected.restore.Init(GL_ARRAY_BUFFER, 0); + expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0); + gl_->EnableVertexAttribArray(kAttribIndex1); + gl_->EnableVertexAttribArray(kAttribIndex2); + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, + DrawElementsClientSideBuffersServiceSideIndices) { + static const float verts[][4] = { + { 12.0f, 23.0f, 34.0f, 45.0f, }, + { 56.0f, 67.0f, 78.0f, 89.0f, }, + { 13.0f, 24.0f, 35.0f, 46.0f, }, + }; + struct Cmds { + EnableVertexAttribArray enable1; + EnableVertexAttribArray enable2; + BindBuffer bind_to_index; + GetMaxValueInBuffer get_max; + BindBuffer bind_to_emu; + BufferData set_size; + BufferSubData copy_data1; + cmd::SetToken set_token1; + VertexAttribPointer set_pointer1; + BufferSubData copy_data2; + cmd::SetToken set_token2; + VertexAttribPointer set_pointer2; + DrawElements draw; + BindBuffer restore; + }; + const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId; + const GLuint kClientIndexBufferId = 0x789; + const GLuint kIndexOffset = 0x40; + const GLuint kMaxIndex = 2; + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kClientStride = sizeof(verts[0]); + const GLsizei kCount = 2; + const GLsizei kSize1 = + arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]); + const GLsizei kSize2 = + arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]); + const GLsizei kEmuOffset1 = 0; + const GLsizei kEmuOffset2 = kSize1; + + const GLsizei kTotalSize = kSize1 + kSize2; + int32 token = 1; + uint32 offset = GLES2Implementation::kStartingOffset; + Cmds expected; + expected.enable1.Init(kAttribIndex1); + expected.enable2.Init(kAttribIndex2); + expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); + expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT, + kIndexOffset, kTransferBufferId, 0); + expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); + expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); + expected.copy_data1.Init( + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, kTransferBufferId, offset); + offset += kSize1; + expected.set_token1.Init(token++); + expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, 0, kEmuOffset1); + expected.copy_data2.Init( + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, kTransferBufferId, offset); + expected.set_token2.Init(token++); + expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, 0, kEmuOffset2); + expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, kIndexOffset); + expected.restore.Init(GL_ARRAY_BUFFER, 0); + + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(kMaxIndex)) + .RetiresOnSaturation(); + + gl_->EnableVertexAttribArray(kAttribIndex1); + gl_->EnableVertexAttribArray(kAttribIndex2); + gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kClientStride, verts); + gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, + reinterpret_cast<const void*>(kIndexOffset)); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) { + static const float verts[1] = { 0.0f, }; + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kStride1 = 12; + const GLsizei kStride2 = 0; + const GLuint kBufferId = 0x123; + const GLint kOffset2 = 0x456; + + // Only one set and one get because the client side buffer's info is stored + // on the client side. + struct Cmds { + BindBuffer bind; + VertexAttribPointer set_pointer; + GetVertexAttribPointerv get_pointer; + }; + Cmds expected; + expected.bind.Init(GL_ARRAY_BUFFER, kBufferId); + expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, + kStride2, kOffset2); + expected.get_pointer.Init(kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, + kTransferBufferId, 0); + + // One call to flush to way for GetVertexAttribPointerv + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(SizedResultHelper<uint32>(kOffset2))) + .RetiresOnSaturation(); + + // Set one client side buffer. + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kStride1, verts); + // Set one VBO + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kStride2, + reinterpret_cast<const void*>(kOffset2)); + // now get them both. + void* ptr1 = NULL; + void* ptr2 = NULL; + + gl_->GetVertexAttribPointerv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr1); + gl_->GetVertexAttribPointerv( + kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr2); + + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(static_cast<const void*>(&verts) == ptr1); + // because the service is not running ptr2 is not read. + EXPECT_TRUE(ptr2 == reinterpret_cast<void*>(kOffset2)); +} + +TEST_F(GLES2ImplementationTest, GetVertexAttrib) { + static const float verts[1] = { 0.0f, }; + const GLuint kAttribIndex1 = 1; + const GLuint kAttribIndex2 = 3; + const GLint kNumComponents1 = 3; + const GLint kNumComponents2 = 2; + const GLsizei kStride1 = 12; + const GLsizei kStride2 = 0; + const GLuint kBufferId = 0x123; + const GLint kOffset2 = 0x456; + + // Only one set and one get because the client side buffer's info is stored + // on the client side. + struct Cmds { + EnableVertexAttribArray enable; + BindBuffer bind; + VertexAttribPointer set_pointer; + GetVertexAttribiv get1; // for getting the buffer from attrib2 + GetVertexAttribfv get2; // for getting the value from attrib1 + }; + Cmds expected; + expected.enable.Init(kAttribIndex1); + expected.bind.Init(GL_ARRAY_BUFFER, kBufferId); + expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, + kStride2, kOffset2); + expected.get1.Init(kAttribIndex2, + GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, + kTransferBufferId, 0); + expected.get2.Init(kAttribIndex1, + GL_CURRENT_VERTEX_ATTRIB, + kTransferBufferId, 0); + + FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f); + + // One call to flush to way for GetVertexAttribiv + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(SizedResultHelper<GLuint>(kBufferId))) + .WillOnce(SetMemory(SizedResultHelper<FourFloats>(current_attrib))) + .RetiresOnSaturation(); + + gl_->EnableVertexAttribArray(kAttribIndex1); + // Set one client side buffer. + gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, + GL_FLOAT, GL_FALSE, kStride1, verts); + // Set one VBO + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2, + GL_FLOAT, GL_FALSE, kStride2, + reinterpret_cast<const void*>(kOffset2)); + // first get the service side once to see that we make a command + GLint buffer_id = 0; + GLint enabled = 0; + GLint size = 0; + GLint stride = 0; + GLint type = 0; + GLint normalized = 1; + float current[4] = { 0.0f, }; + + gl_->GetVertexAttribiv( + kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id); + EXPECT_EQ(kBufferId, static_cast<GLuint>(buffer_id)); + gl_->GetVertexAttribiv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id); + gl_->GetVertexAttribiv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled); + gl_->GetVertexAttribiv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size); + gl_->GetVertexAttribiv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride); + gl_->GetVertexAttribiv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type); + gl_->GetVertexAttribiv( + kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized); + gl_->GetVertexAttribfv( + kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, ¤t[0]); + + EXPECT_EQ(0, buffer_id); + EXPECT_EQ(GL_TRUE, enabled); + EXPECT_EQ(kNumComponents1, size); + EXPECT_EQ(kStride1, stride); + EXPECT_EQ(GL_FLOAT, type); + EXPECT_EQ(GL_FALSE, normalized); + EXPECT_EQ(0, memcmp(¤t_attrib, ¤t, sizeof(current_attrib))); + + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, ReservedIds) { + // Only the get error command should be issued. + struct Cmds { + GetError get; + }; + Cmds expected; + expected.get.Init(kTransferBufferId, 0); + + // One call to flush to way for GetError + EXPECT_CALL(*command_buffer_, OnFlush(_)) + .WillOnce(SetMemory(GLuint(GL_NO_ERROR))) + .RetiresOnSaturation(); + + gl_->BindBuffer( + GL_ARRAY_BUFFER, + GLES2Implementation::kClientSideArrayId); + gl_->BindBuffer( + GL_ARRAY_BUFFER, + GLES2Implementation::kClientSideElementArrayId); + gl_->BindFramebuffer( + GL_FRAMEBUFFER, + GLES2Implementation::kClientSideArrayId); + gl_->BindFramebuffer( + GL_FRAMEBUFFER, + GLES2Implementation::kClientSideElementArrayId); + gl_->BindRenderbuffer( + GL_RENDERBUFFER, + GLES2Implementation::kClientSideArrayId); + gl_->BindRenderbuffer( + GL_RENDERBUFFER, + GLES2Implementation::kClientSideElementArrayId); + gl_->BindTexture( + GL_TEXTURE_2D, + GLES2Implementation::kClientSideArrayId); + gl_->BindTexture( + GL_TEXTURE_2D, + GLES2Implementation::kClientSideElementArrayId); + GLenum err = gl_->GetError(); + EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), err); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +#endif // defined(GLES2_SUPPORT_CLIENT_SIDE_BUFFERS) + + +} // namespace gles2 +} // namespace gpu + + |