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