1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/client/vertex_array_object_manager.h"
6
7 #include <GLES2/gl2ext.h>
8 #include <GLES3/gl3.h>
9
10 #include <stddef.h>
11 #include <stdint.h>
12
13 #include <memory>
14
15 #include "base/stl_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace gpu {
19 namespace gles2 {
20
21 class VertexArrayObjectManagerTest : public testing::Test {
22 protected:
23 static const GLuint kMaxAttribs = 4;
24 static const GLuint kClientSideArrayBuffer = 0x1234;
25 static const GLuint kClientSideElementArrayBuffer = 0x1235;
26 static const bool kSupportClientSideArrays = true;
27
SetUp()28 void SetUp() override {
29 manager_.reset(new VertexArrayObjectManager(
30 kMaxAttribs,
31 kClientSideArrayBuffer,
32 kClientSideElementArrayBuffer,
33 kSupportClientSideArrays));
34 }
TearDown()35 void TearDown() override {}
36
37 std::unique_ptr<VertexArrayObjectManager> manager_;
38 };
39
40 // GCC requires these declarations, but MSVC requires they not be present
41 #ifndef _MSC_VER
42 const GLuint VertexArrayObjectManagerTest::kMaxAttribs;
43 const GLuint VertexArrayObjectManagerTest::kClientSideArrayBuffer;
44 const GLuint VertexArrayObjectManagerTest::kClientSideElementArrayBuffer;
45 #endif
46
TEST_F(VertexArrayObjectManagerTest,Basic)47 TEST_F(VertexArrayObjectManagerTest, Basic) {
48 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
49 // Check out of bounds access.
50 uint32_t param;
51 void* ptr;
52 EXPECT_FALSE(manager_->GetVertexAttrib(
53 kMaxAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, ¶m));
54 EXPECT_FALSE(manager_->GetAttribPointer(
55 kMaxAttribs, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr));
56 // Check defaults.
57 for (GLuint ii = 0; ii < kMaxAttribs; ++ii) {
58 EXPECT_TRUE(manager_->GetVertexAttrib(
59 ii, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, ¶m));
60 EXPECT_EQ(0u, param);
61 EXPECT_TRUE(manager_->GetVertexAttrib(
62 ii, GL_VERTEX_ATTRIB_ARRAY_ENABLED, ¶m));
63 EXPECT_EQ(0u, param);
64 EXPECT_TRUE(manager_->GetVertexAttrib(
65 ii, GL_VERTEX_ATTRIB_ARRAY_SIZE, ¶m));
66 EXPECT_EQ(4u, param);
67 EXPECT_TRUE(manager_->GetVertexAttrib(
68 ii, GL_VERTEX_ATTRIB_ARRAY_TYPE, ¶m));
69 EXPECT_EQ(static_cast<uint32_t>(GL_FLOAT), param);
70 EXPECT_TRUE(manager_->GetVertexAttrib(
71 ii, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, ¶m));
72 EXPECT_EQ(0u, param);
73 EXPECT_TRUE(manager_->GetAttribPointer(
74 ii, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr));
75 EXPECT_TRUE(nullptr == ptr);
76 }
77 }
78
TEST_F(VertexArrayObjectManagerTest,UnbindBuffer)79 TEST_F(VertexArrayObjectManagerTest, UnbindBuffer) {
80 const GLuint kBufferToUnbind = 123;
81 const GLuint kBufferToRemain = 456;
82 const GLuint kElementArray = 789;
83 bool changed = false;
84 GLuint ids[2] = { 1, 3, };
85 manager_->GenVertexArrays(base::size(ids), ids);
86 // Bind buffers to attribs on 2 vaos.
87 for (size_t ii = 0; ii < base::size(ids); ++ii) {
88 EXPECT_TRUE(manager_->BindVertexArray(ids[ii], &changed));
89 EXPECT_TRUE(manager_->SetAttribPointer(
90 kBufferToUnbind, 0, 4, GL_FLOAT, false, 0, 0, GL_FALSE));
91 EXPECT_TRUE(manager_->SetAttribPointer(
92 kBufferToRemain, 1, 4, GL_FLOAT, false, 0, 0, GL_FALSE));
93 EXPECT_TRUE(manager_->SetAttribPointer(
94 kBufferToUnbind, 2, 4, GL_FLOAT, false, 0, 0, GL_FALSE));
95 EXPECT_TRUE(manager_->SetAttribPointer(
96 kBufferToRemain, 3, 4, GL_FLOAT, false, 0, 0, GL_FALSE));
97 for (size_t jj = 0; jj < 4u; ++jj) {
98 manager_->SetAttribEnable(jj, true);
99 }
100 manager_->BindElementArray(kElementArray);
101 }
102 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
103 EXPECT_TRUE(manager_->BindVertexArray(ids[0], &changed));
104 // Unbind the buffer.
105 manager_->UnbindBuffer(kBufferToUnbind);
106 manager_->UnbindBuffer(kElementArray);
107 // The attribs are still enabled but their buffer is 0.
108 EXPECT_TRUE(manager_->HaveEnabledClientSideBuffers());
109 // Check the status of the bindings.
110 static const uint32_t expected[][4] = {
111 {
112 0, kBufferToRemain, 0, kBufferToRemain,
113 },
114 {
115 kBufferToUnbind, kBufferToRemain, kBufferToUnbind, kBufferToRemain,
116 },
117 };
118 static const GLuint expected_element_array[] = {
119 0, kElementArray,
120 };
121 for (size_t ii = 0; ii < base::size(ids); ++ii) {
122 EXPECT_TRUE(manager_->BindVertexArray(ids[ii], &changed));
123 for (size_t jj = 0; jj < 4; ++jj) {
124 uint32_t param = 1;
125 EXPECT_TRUE(manager_->GetVertexAttrib(
126 jj, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, ¶m));
127 EXPECT_EQ(expected[ii][jj], param)
128 << "id: " << ids[ii] << ", attrib: " << jj;
129 }
130 EXPECT_EQ(expected_element_array[ii],
131 manager_->bound_element_array_buffer());
132 }
133
134 // The vao that was not bound still has all service side bufferws.
135 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
136
137 // Make sure unbinding 0 does not effect count incorrectly.
138 EXPECT_TRUE(manager_->BindVertexArray(0, &changed));
139 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
140 manager_->SetAttribEnable(2, true);
141 manager_->UnbindBuffer(0);
142 manager_->SetAttribEnable(2, false);
143 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
144 }
145
TEST_F(VertexArrayObjectManagerTest,GetSet)146 TEST_F(VertexArrayObjectManagerTest, GetSet) {
147 const char* dummy = "dummy";
148 const void* p = reinterpret_cast<const void*>(dummy);
149 manager_->SetAttribEnable(1, true);
150 manager_->SetAttribPointer(123, 1, 3, GL_BYTE, true, 3, p, GL_TRUE);
151 uint32_t param;
152 void* ptr;
153 EXPECT_TRUE(manager_->GetVertexAttrib(
154 1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, ¶m));
155 EXPECT_EQ(123u, param);
156 EXPECT_TRUE(manager_->GetVertexAttrib(
157 1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, ¶m));
158 EXPECT_NE(0u, param);
159 EXPECT_TRUE(manager_->GetVertexAttrib(
160 1, GL_VERTEX_ATTRIB_ARRAY_SIZE, ¶m));
161 EXPECT_EQ(3u, param);
162 EXPECT_TRUE(manager_->GetVertexAttrib(
163 1, GL_VERTEX_ATTRIB_ARRAY_TYPE, ¶m));
164 EXPECT_EQ(static_cast<uint32_t>(GL_BYTE), param);
165 EXPECT_TRUE(manager_->GetVertexAttrib(
166 1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, ¶m));
167 EXPECT_NE(0u, param);
168 EXPECT_TRUE(manager_->GetVertexAttrib(
169 1, GL_VERTEX_ATTRIB_ARRAY_INTEGER, ¶m));
170 EXPECT_EQ(1u, param);
171 EXPECT_TRUE(manager_->GetAttribPointer(
172 1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr));
173 EXPECT_EQ(p, ptr);
174
175 // Check that getting the divisor is passed to the service.
176 // This is because the divisor is an optional feature which
177 // only the service can validate.
178 EXPECT_FALSE(manager_->GetVertexAttrib(
179 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE, ¶m));
180 }
181
TEST_F(VertexArrayObjectManagerTest,HaveEnabledClientSideArrays)182 TEST_F(VertexArrayObjectManagerTest, HaveEnabledClientSideArrays) {
183 // Check turning on an array.
184 manager_->SetAttribEnable(1, true);
185 EXPECT_TRUE(manager_->HaveEnabledClientSideBuffers());
186 // Check turning off an array.
187 manager_->SetAttribEnable(1, false);
188 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
189 // Check turning on an array and assigning a buffer.
190 manager_->SetAttribEnable(1, true);
191 manager_->SetAttribPointer(123, 1, 3, GL_BYTE, true, 3, nullptr, GL_FALSE);
192 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
193 // Check unassigning a buffer.
194 manager_->SetAttribPointer(0, 1, 3, GL_BYTE, true, 3, nullptr, GL_FALSE);
195 EXPECT_TRUE(manager_->HaveEnabledClientSideBuffers());
196 // Check disabling the array.
197 manager_->SetAttribEnable(1, false);
198 EXPECT_FALSE(manager_->HaveEnabledClientSideBuffers());
199 }
200
TEST_F(VertexArrayObjectManagerTest,BindElementArray)201 TEST_F(VertexArrayObjectManagerTest, BindElementArray) {
202 bool changed = false;
203 GLuint ids[2] = { 1, 3, };
204 manager_->GenVertexArrays(base::size(ids), ids);
205
206 // Check the default element array is 0.
207 EXPECT_EQ(0u, manager_->bound_element_array_buffer());
208 // Check binding the same array does not need a service call.
209 EXPECT_FALSE(manager_->BindElementArray(0u));
210 // Check binding a new element array requires a service call.
211 EXPECT_TRUE(manager_->BindElementArray(55u));
212 // Check the element array was bound.
213 EXPECT_EQ(55u, manager_->bound_element_array_buffer());
214 // Check binding the same array does not need a service call.
215 EXPECT_FALSE(manager_->BindElementArray(55u));
216
217 // Check with a new vao.
218 EXPECT_TRUE(manager_->BindVertexArray(1, &changed));
219 // Check the default element array is 0.
220 EXPECT_EQ(0u, manager_->bound_element_array_buffer());
221 // Check binding a new element array requires a service call.
222 EXPECT_TRUE(manager_->BindElementArray(11u));
223 // Check the element array was bound.
224 EXPECT_EQ(11u, manager_->bound_element_array_buffer());
225 // Check binding the same array does not need a service call.
226 EXPECT_FALSE(manager_->BindElementArray(11u));
227
228 // check switching vao bindings returns the correct element array.
229 EXPECT_TRUE(manager_->BindVertexArray(3, &changed));
230 EXPECT_EQ(0u, manager_->bound_element_array_buffer());
231 EXPECT_TRUE(manager_->BindVertexArray(0, &changed));
232 EXPECT_EQ(55u, manager_->bound_element_array_buffer());
233 EXPECT_TRUE(manager_->BindVertexArray(1, &changed));
234 EXPECT_EQ(11u, manager_->bound_element_array_buffer());
235 }
236
TEST_F(VertexArrayObjectManagerTest,GenBindDelete)237 TEST_F(VertexArrayObjectManagerTest, GenBindDelete) {
238 // Check unknown array fails.
239 bool changed = false;
240 EXPECT_FALSE(manager_->BindVertexArray(123, &changed));
241 EXPECT_FALSE(changed);
242
243 GLuint ids[2] = { 1, 3, };
244 manager_->GenVertexArrays(base::size(ids), ids);
245 // Check Genned arrays succeed.
246 EXPECT_TRUE(manager_->BindVertexArray(1, &changed));
247 EXPECT_TRUE(changed);
248 EXPECT_TRUE(manager_->BindVertexArray(3, &changed));
249 EXPECT_TRUE(changed);
250
251 // Check binding the same array returns changed as false.
252 EXPECT_TRUE(manager_->BindVertexArray(3, &changed));
253 EXPECT_FALSE(changed);
254
255 // Check deleted ararys fail to bind
256 manager_->DeleteVertexArrays(2, ids);
257 EXPECT_FALSE(manager_->BindVertexArray(1, &changed));
258 EXPECT_FALSE(changed);
259 EXPECT_FALSE(manager_->BindVertexArray(3, &changed));
260 EXPECT_FALSE(changed);
261
262 // Check binding 0 returns changed as false since it's
263 // already bound.
264 EXPECT_TRUE(manager_->BindVertexArray(0, &changed));
265 EXPECT_FALSE(changed);
266 }
267
TEST_F(VertexArrayObjectManagerTest,IsReservedId)268 TEST_F(VertexArrayObjectManagerTest, IsReservedId) {
269 EXPECT_TRUE(manager_->IsReservedId(kClientSideArrayBuffer));
270 EXPECT_TRUE(manager_->IsReservedId(kClientSideElementArrayBuffer));
271 EXPECT_FALSE(manager_->IsReservedId(0));
272 EXPECT_FALSE(manager_->IsReservedId(1));
273 EXPECT_FALSE(manager_->IsReservedId(2));
274 }
275
276 } // namespace gles2
277 } // namespace gpu
278
279