1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "GLSnapshotTestStateUtils.h"
16 #include "GLSnapshotTesting.h"
17 #include "OpenGLTestContext.h"
18
19 #include <gtest/gtest.h>
20
21 #include <algorithm>
22
23 namespace gfxstream {
24 namespace gl {
25 namespace {
26
27 enum class GlVertexAttribMode { SingleValue = 0, Array = 1, Buffer = 2 };
28
29 struct GlVertexAttrib {
30 GlVertexAttribMode mode;
31 GlValues values;
32 GLint size;
33 GLenum type;
34 GLboolean normalized;
35 GLsizei stride;
36 GLboolean enabled;
37 GLvoid* pointer;
38 GLuint bufferBinding;
39 };
40
41 static const GlVertexAttrib kGLES2DefaultVertexAttrib = {
42 .mode = GlVertexAttribMode::SingleValue,
43 .values = {.ints = {}, .floats = {0, 0, 0, 1}},
44 .size = 4,
45 .type = GL_FLOAT,
46 .normalized = GL_FALSE,
47 .stride = 0,
48 .enabled = GL_FALSE,
49 .pointer = nullptr,
50 .bufferBinding = 0};
51
52 static const GlBufferData kTestAttachedBuffer = {.size = 16,
53 .bytes = nullptr,
54 .usage = GL_STATIC_DRAW};
55
56 class SnapshotGlVertexAttributesTest
57 : public SnapshotSetValueTest<GlVertexAttrib> {
58 public:
stateCheck(GlVertexAttrib expected)59 virtual void stateCheck(GlVertexAttrib expected) override {
60 EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_ENABLED,
61 expected.enabled));
62 }
63
stateChange()64 virtual void stateChange() override {
65 GlVertexAttrib changed = *m_changed_value;
66 if (changed.enabled) {
67 gl->glEnableVertexAttribArray(m_index);
68 } else {
69 gl->glDisableVertexAttribArray(m_index);
70 }
71 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
72 }
73
selectIndex(GLuint index)74 void selectIndex(GLuint index) {
75 GLint maxAttribs;
76 gl->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
77 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
78 if (index >= maxAttribs) {
79 fprintf(stderr,
80 "cannot select index %d: GL_MAX_VERTEX_ATTRIBS is %d.\n",
81 index, maxAttribs);
82 return;
83 }
84 m_index = index;
85 }
86
87 protected:
compareFloatParameter(GLenum paramName,GLfloat expected)88 testing::AssertionResult compareFloatParameter(GLenum paramName,
89 GLfloat expected) {
90 std::vector<GLfloat> v = {expected};
91 return compareFloatParameter(paramName, v);
92 }
93
compareFloatParameter(GLenum paramName,const std::vector<GLfloat> & expected)94 testing::AssertionResult compareFloatParameter(
95 GLenum paramName,
96 const std::vector<GLfloat>& expected) {
97 std::vector<GLfloat> values;
98 values.resize(std::max((GLuint)4, (GLuint)expected.size()));
99 gl->glGetVertexAttribfv(m_index, paramName, &(values[0]));
100 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
101 return compareVector<GLfloat>(
102 expected, values,
103 "float(s) for parameter " + describeGlEnum(paramName) +
104 " of vertex attribute " + std::to_string(m_index));
105 }
106
compareIntParameter(GLenum paramName,GLint expected)107 testing::AssertionResult compareIntParameter(GLenum paramName,
108 GLint expected) {
109 std::vector<GLint> v = {expected};
110 return compareIntParameter(paramName, v);
111 }
112
compareIntParameter(GLenum paramName,const std::vector<GLint> & expected)113 testing::AssertionResult compareIntParameter(
114 GLenum paramName,
115 const std::vector<GLint>& expected) {
116 std::vector<GLint> values;
117 values.resize(std::max((GLuint)4, (GLuint)expected.size()));
118 gl->glGetVertexAttribiv(m_index, paramName, &(values[0]));
119 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
120 return compareVector<GLint>(
121 expected, values,
122 "int(s) for parameter " + describeGlEnum(paramName) +
123 " of vertex attribute " + std::to_string(m_index));
124 }
125
126 GLuint m_index = 0;
127 };
128
129 class SnapshotGlVertexAttribSingleValueTest
130 : public SnapshotGlVertexAttributesTest {
131 public:
stateCheck(GlVertexAttrib expected)132 void stateCheck(GlVertexAttrib expected) override {
133 SnapshotGlVertexAttributesTest::stateCheck(expected);
134
135 // check current element value
136 switch (expected.type) {
137 case GL_BYTE:
138 case GL_UNSIGNED_BYTE:
139 case GL_SHORT:
140 case GL_UNSIGNED_SHORT:
141 case GL_FIXED:
142 EXPECT_TRUE(compareIntParameter(GL_CURRENT_VERTEX_ATTRIB,
143 expected.values.ints));
144 break;
145 case GL_FLOAT:
146 EXPECT_TRUE(compareFloatParameter(GL_CURRENT_VERTEX_ATTRIB,
147 expected.values.floats));
148 break;
149 default:
150 ADD_FAILURE() << "Unexpected type " << expected.type
151 << " for vertex attribute " << m_index;
152 }
153 }
154
stateChange()155 void stateChange() override {
156 SnapshotGlVertexAttributesTest::stateChange();
157 GlVertexAttrib changed = *m_changed_value;
158 switch (changed.type) {
159 case GL_BYTE:
160 case GL_UNSIGNED_BYTE:
161 case GL_SHORT:
162 case GL_UNSIGNED_SHORT:
163 case GL_FIXED:
164 // TODO(benzene): support GLES3+
165 FAIL() << "GLES2 only supports float vertex attributes "
166 "(VertexAttrib{1234}f).";
167 case GL_FLOAT:
168 switch (changed.values.floats.size()) {
169 case 1:
170 gl->glVertexAttrib1fv(
171 m_index, (GLfloat*)&changed.values.floats[0]);
172 break;
173 case 2:
174 gl->glVertexAttrib2fv(
175 m_index, (GLfloat*)&changed.values.floats[0]);
176 break;
177 case 3:
178 gl->glVertexAttrib3fv(
179 m_index, (GLfloat*)&changed.values.floats[0]);
180 break;
181 case 4:
182 gl->glVertexAttrib4fv(
183 m_index, (GLfloat*)&changed.values.floats[0]);
184 break;
185 default:
186 ADD_FAILURE() << "Unsupported size " << changed.size
187 << " for vertex attribute " << m_index;
188 }
189 break;
190 default:
191 ADD_FAILURE() << "Unsupported type " << changed.type
192 << " for vertex attribute " << m_index;
193 }
194 }
195 };
196
197 class SnapshotGlVertexAttribArrayTest : public SnapshotGlVertexAttributesTest {
198 public:
stateCheck(GlVertexAttrib expected)199 virtual void stateCheck(GlVertexAttrib expected) override {
200 SnapshotGlVertexAttributesTest::stateCheck(expected);
201 // check parameters
202 EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_SIZE,
203 expected.size));
204 EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_TYPE,
205 expected.type));
206 EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_STRIDE,
207 expected.stride));
208 EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED,
209 expected.normalized));
210 EXPECT_TRUE(compareIntParameter(GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
211 expected.bufferBinding));
212
213 GLvoid* pointer;
214 gl->glGetVertexAttribPointerv(m_index, GL_VERTEX_ATTRIB_ARRAY_POINTER,
215 &pointer);
216 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
217 EXPECT_EQ(expected.pointer, pointer);
218 }
219
stateChange()220 virtual void stateChange() override {
221 SnapshotGlVertexAttributesTest::stateChange();
222 GlVertexAttrib changed = *m_changed_value;
223 gl->glVertexAttribPointer(m_index, changed.size, changed.type,
224 changed.normalized, changed.stride,
225 changed.pointer);
226 }
227 };
228
229 class SnapshotGlVertexAttribBufferTest
230 : public SnapshotGlVertexAttribArrayTest {
231 public:
stateCheck(GlVertexAttrib expected)232 void stateCheck(GlVertexAttrib expected) override {
233 SnapshotGlVertexAttribArrayTest::stateCheck(expected);
234 }
235
stateChange()236 void stateChange() override {
237 GlVertexAttrib changed = *m_changed_value;
238
239 // Set up buffer to be bound before glVertexAttribPointer,
240 // which will copy ARRAY_BUFFER_BINDING into the attrib's binding
241 if (gl->glIsBuffer(changed.bufferBinding) == GL_TRUE) {
242 gl->glBindBuffer(GL_ARRAY_BUFFER, changed.bufferBinding);
243 EXPECT_EQ(GL_NO_ERROR, gl->glGetError())
244 << "Failed to bind buffer " << changed.bufferBinding;
245 GLint bindresult;
246 gl->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &bindresult);
247 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
248 } else {
249 ADD_FAILURE() << "Tried to bind buffer with vertex attributes but "
250 << changed.bufferBinding << " is not a valid buffer.";
251 }
252
253 SnapshotGlVertexAttribArrayTest::stateChange();
254
255 if (changed.bufferBinding != 0) {
256 // Clear the array buffer binding
257 gl->glBindBuffer(GL_ARRAY_BUFFER, 0);
258 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
259
260 GLint bindresult;
261 gl->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &bindresult);
262 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
263 }
264 }
265 };
266
TEST_F(SnapshotGlVertexAttribSingleValueTest,PreserveCurrentFloatAttrib)267 TEST_F(SnapshotGlVertexAttribSingleValueTest, PreserveCurrentFloatAttrib) {
268 selectIndex(31);
269 GlVertexAttrib testAttrib = kGLES2DefaultVertexAttrib;
270 testAttrib.values = {.ints = {}, .floats = {.1, .3}},
271 setExpectedValues(kGLES2DefaultVertexAttrib, testAttrib);
272 doCheckedSnapshot();
273 }
274
TEST_F(SnapshotGlVertexAttribArrayTest,DISABLED_PreserveArrayProperties)275 TEST_F(SnapshotGlVertexAttribArrayTest, DISABLED_PreserveArrayProperties) {
276 selectIndex(5);
277 GLfloat testArrayContents[] = {2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f};
278 GlVertexAttrib arrayAttrib = kGLES2DefaultVertexAttrib;
279 arrayAttrib.mode = GlVertexAttribMode::Array;
280 arrayAttrib.size = 3;
281 arrayAttrib.stride = sizeof(GLfloat) * 3;
282 arrayAttrib.normalized = GL_TRUE;
283 arrayAttrib.enabled = GL_TRUE;
284 arrayAttrib.pointer = testArrayContents;
285 setExpectedValues(kGLES2DefaultVertexAttrib, arrayAttrib);
286 doCheckedSnapshot();
287 }
288
TEST_F(SnapshotGlVertexAttribBufferTest,AttachArrayBuffer)289 TEST_F(SnapshotGlVertexAttribBufferTest, AttachArrayBuffer) {
290 selectIndex(15);
291 GLfloat testBuffContents[] = {
292 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f,
293 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f,
294 };
295 GlBufferData data = kTestAttachedBuffer;
296 data.bytes = testBuffContents;
297 GLuint buffer = createBuffer(gl, data);
298 GlVertexAttrib withBuffer = kGLES2DefaultVertexAttrib;
299 withBuffer.mode = GlVertexAttribMode::Buffer;
300 withBuffer.enabled = GL_TRUE;
301 withBuffer.pointer = reinterpret_cast<GLvoid*>(2); // offset
302 withBuffer.bufferBinding = buffer;
303 setExpectedValues(kGLES2DefaultVertexAttrib, withBuffer);
304 doCheckedSnapshot();
305 }
306
307 } // namespace
308 } // namespace gl
309 } // namespace gfxstream
310