| // Copyright 2012 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "gpu/command_buffer/client/vertex_array_object_manager.h" | |
| #include <GLES2/gl2ext.h> | |
| #include <GLES3/gl3.h> | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <array> | |
| #include <memory> | |
| #include "base/compiler_specific.h" | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| namespace gpu { | |
| namespace gles2 { | |
| class VertexArrayObjectManagerTest : public testing::Test { | |
| protected: | |
| static const GLuint kMaxAttribs = 4; | |
| void SetUp() override { | |
| manager_ = std::make_unique<VertexArrayObjectManager>(kMaxAttribs); | |
| } | |
| void TearDown() override {} | |
| std::unique_ptr<VertexArrayObjectManager> manager_; | |
| }; | |
| const GLuint VertexArrayObjectManagerTest::kMaxAttribs; | |
| TEST_F(VertexArrayObjectManagerTest, Basic) { | |
| // Check out of bounds access. | |
| uint32_t param; | |
| void* ptr; | |
| EXPECT_FALSE(manager_->GetVertexAttrib( | |
| kMaxAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, ¶m)); | |
| EXPECT_FALSE(manager_->GetAttribPointer( | |
| kMaxAttribs, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr)); | |
| // Check defaults. | |
| for (GLuint ii = 0; ii < kMaxAttribs; ++ii) { | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| ii, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, ¶m)); | |
| EXPECT_EQ(0u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| ii, GL_VERTEX_ATTRIB_ARRAY_ENABLED, ¶m)); | |
| EXPECT_EQ(0u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| ii, GL_VERTEX_ATTRIB_ARRAY_SIZE, ¶m)); | |
| EXPECT_EQ(4u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| ii, GL_VERTEX_ATTRIB_ARRAY_TYPE, ¶m)); | |
| EXPECT_EQ(static_cast<uint32_t>(GL_FLOAT), param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| ii, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, ¶m)); | |
| EXPECT_EQ(0u, param); | |
| EXPECT_TRUE(manager_->GetAttribPointer( | |
| ii, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr)); | |
| EXPECT_TRUE(nullptr == ptr); | |
| } | |
| } | |
| TEST_F(VertexArrayObjectManagerTest, UnbindBuffer) { | |
| const GLuint kBufferToUnbind = 123; | |
| const GLuint kBufferToRemain = 456; | |
| const GLuint kElementArray = 789; | |
| bool changed = false; | |
| std::array<GLuint, 2> ids = { | |
| 1, | |
| 3, | |
| }; | |
| manager_->GenVertexArrays(std::size(ids), ids.data()); | |
| // Bind buffers to attribs on 2 vaos. | |
| for (GLuint id : ids) { | |
| EXPECT_TRUE(manager_->BindVertexArray(id, &changed)); | |
| EXPECT_TRUE(manager_->SetAttribPointer( | |
| kBufferToUnbind, 0, 4, GL_FLOAT, false, 0, 0, GL_FALSE)); | |
| EXPECT_TRUE(manager_->SetAttribPointer( | |
| kBufferToRemain, 1, 4, GL_FLOAT, false, 0, 0, GL_FALSE)); | |
| EXPECT_TRUE(manager_->SetAttribPointer( | |
| kBufferToUnbind, 2, 4, GL_FLOAT, false, 0, 0, GL_FALSE)); | |
| EXPECT_TRUE(manager_->SetAttribPointer( | |
| kBufferToRemain, 3, 4, GL_FLOAT, false, 0, 0, GL_FALSE)); | |
| for (size_t jj = 0; jj < 4u; ++jj) { | |
| manager_->SetAttribEnable(jj, true); | |
| } | |
| manager_->BindElementArray(kElementArray); | |
| } | |
| EXPECT_TRUE(manager_->BindVertexArray(ids[0], &changed)); | |
| // Unbind the buffer. | |
| manager_->UnbindBuffer(kBufferToUnbind); | |
| manager_->UnbindBuffer(kElementArray); | |
| // Check the status of the bindings. | |
| static const auto expected = std::to_array<std::array<const uint32_t, 4>>({ | |
| { | |
| 0, | |
| kBufferToRemain, | |
| 0, | |
| kBufferToRemain, | |
| }, | |
| { | |
| kBufferToUnbind, | |
| kBufferToRemain, | |
| kBufferToUnbind, | |
| kBufferToRemain, | |
| }, | |
| }); | |
| static const auto expected_element_array = std::to_array<GLuint>({ | |
| 0, | |
| kElementArray, | |
| }); | |
| for (size_t ii = 0; ii < std::size(ids); ++ii) { | |
| EXPECT_TRUE(manager_->BindVertexArray(ids[ii], &changed)); | |
| for (size_t jj = 0; jj < 4; ++jj) { | |
| uint32_t param = 1; | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| jj, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, ¶m)); | |
| EXPECT_EQ(expected[ii][jj], param) | |
| << "id: " << ids[ii] << ", attrib: " << jj; | |
| } | |
| EXPECT_EQ(expected_element_array[ii], | |
| manager_->bound_element_array_buffer()); | |
| } | |
| } | |
| TEST_F(VertexArrayObjectManagerTest, GetSet) { | |
| const char* dummy = "dummy"; | |
| const void* p = reinterpret_cast<const void*>(dummy); | |
| manager_->SetAttribEnable(1, true); | |
| manager_->SetAttribPointer(123, 1, 3, GL_BYTE, true, 3, p, GL_TRUE); | |
| uint32_t param; | |
| void* ptr; | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, ¶m)); | |
| EXPECT_EQ(123u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, ¶m)); | |
| EXPECT_NE(0u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_SIZE, ¶m)); | |
| EXPECT_EQ(3u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_TYPE, ¶m)); | |
| EXPECT_EQ(static_cast<uint32_t>(GL_BYTE), param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, ¶m)); | |
| EXPECT_NE(0u, param); | |
| EXPECT_TRUE(manager_->GetVertexAttrib( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_INTEGER, ¶m)); | |
| EXPECT_EQ(1u, param); | |
| EXPECT_TRUE(manager_->GetAttribPointer( | |
| 1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr)); | |
| EXPECT_EQ(p, ptr); | |
| // Check that getting the divisor is passed to the service. | |
| // This is because the divisor is an optional feature which | |
| // only the service can validate. | |
| EXPECT_FALSE(manager_->GetVertexAttrib( | |
| 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE, ¶m)); | |
| } | |
| TEST_F(VertexArrayObjectManagerTest, BindElementArray) { | |
| bool changed = false; | |
| GLuint ids[2] = { 1, 3, }; | |
| manager_->GenVertexArrays(std::size(ids), ids); | |
| // Check the default element array is 0. | |
| EXPECT_EQ(0u, manager_->bound_element_array_buffer()); | |
| // Check binding the same array does not need a service call. | |
| EXPECT_FALSE(manager_->BindElementArray(0u)); | |
| // Check binding a new element array requires a service call. | |
| EXPECT_TRUE(manager_->BindElementArray(55u)); | |
| // Check the element array was bound. | |
| EXPECT_EQ(55u, manager_->bound_element_array_buffer()); | |
| // Check binding the same array does not need a service call. | |
| EXPECT_FALSE(manager_->BindElementArray(55u)); | |
| // Check with a new vao. | |
| EXPECT_TRUE(manager_->BindVertexArray(1, &changed)); | |
| // Check the default element array is 0. | |
| EXPECT_EQ(0u, manager_->bound_element_array_buffer()); | |
| // Check binding a new element array requires a service call. | |
| EXPECT_TRUE(manager_->BindElementArray(11u)); | |
| // Check the element array was bound. | |
| EXPECT_EQ(11u, manager_->bound_element_array_buffer()); | |
| // Check binding the same array does not need a service call. | |
| EXPECT_FALSE(manager_->BindElementArray(11u)); | |
| // check switching vao bindings returns the correct element array. | |
| EXPECT_TRUE(manager_->BindVertexArray(3, &changed)); | |
| EXPECT_EQ(0u, manager_->bound_element_array_buffer()); | |
| EXPECT_TRUE(manager_->BindVertexArray(0, &changed)); | |
| EXPECT_EQ(55u, manager_->bound_element_array_buffer()); | |
| EXPECT_TRUE(manager_->BindVertexArray(1, &changed)); | |
| EXPECT_EQ(11u, manager_->bound_element_array_buffer()); | |
| } | |
| TEST_F(VertexArrayObjectManagerTest, GenBindDelete) { | |
| // Check unknown array fails. | |
| bool changed = false; | |
| EXPECT_FALSE(manager_->BindVertexArray(123, &changed)); | |
| EXPECT_FALSE(changed); | |
| GLuint ids[2] = { 1, 3, }; | |
| manager_->GenVertexArrays(std::size(ids), ids); | |
| // Check Genned arrays succeed. | |
| EXPECT_TRUE(manager_->BindVertexArray(1, &changed)); | |
| EXPECT_TRUE(changed); | |
| EXPECT_TRUE(manager_->BindVertexArray(3, &changed)); | |
| EXPECT_TRUE(changed); | |
| // Check binding the same array returns changed as false. | |
| EXPECT_TRUE(manager_->BindVertexArray(3, &changed)); | |
| EXPECT_FALSE(changed); | |
| // Check deleted ararys fail to bind | |
| manager_->DeleteVertexArrays(2, ids); | |
| EXPECT_FALSE(manager_->BindVertexArray(1, &changed)); | |
| EXPECT_FALSE(changed); | |
| EXPECT_FALSE(manager_->BindVertexArray(3, &changed)); | |
| EXPECT_FALSE(changed); | |
| // Check binding 0 returns changed as false since it's | |
| // already bound. | |
| EXPECT_TRUE(manager_->BindVertexArray(0, &changed)); | |
| EXPECT_FALSE(changed); | |
| } | |
| } // namespace gles2 | |
| } // namespace gpu |