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