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, &param));
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, &param));
60     EXPECT_EQ(0u, param);
61     EXPECT_TRUE(manager_->GetVertexAttrib(
62         ii, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &param));
63     EXPECT_EQ(0u, param);
64     EXPECT_TRUE(manager_->GetVertexAttrib(
65         ii, GL_VERTEX_ATTRIB_ARRAY_SIZE, &param));
66     EXPECT_EQ(4u, param);
67     EXPECT_TRUE(manager_->GetVertexAttrib(
68         ii, GL_VERTEX_ATTRIB_ARRAY_TYPE, &param));
69     EXPECT_EQ(static_cast<uint32_t>(GL_FLOAT), param);
70     EXPECT_TRUE(manager_->GetVertexAttrib(
71         ii, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &param));
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, &param));
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, &param));
155   EXPECT_EQ(123u, param);
156   EXPECT_TRUE(manager_->GetVertexAttrib(
157       1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &param));
158   EXPECT_NE(0u, param);
159   EXPECT_TRUE(manager_->GetVertexAttrib(
160       1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &param));
161   EXPECT_EQ(3u, param);
162   EXPECT_TRUE(manager_->GetVertexAttrib(
163       1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &param));
164   EXPECT_EQ(static_cast<uint32_t>(GL_BYTE), param);
165   EXPECT_TRUE(manager_->GetVertexAttrib(
166       1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &param));
167   EXPECT_NE(0u, param);
168   EXPECT_TRUE(manager_->GetVertexAttrib(
169       1, GL_VERTEX_ATTRIB_ARRAY_INTEGER, &param));
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, &param));
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