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 "GLSnapshotTesting.h"
16
17 #include <gtest/gtest.h>
18
19 #include <string>
20
21 namespace emugl {
22
23 static const char kTestVertexShaderSource[] = R"(
24 attribute vec4 position;
25 uniform mat4 projection;
26 uniform mat4 transform;
27 uniform mat4 screenSpace;
28 varying float linear;
29 void main(void) {
30 vec4 transformedPosition = projection * transform * position;
31 gl_Position = transformedPosition;
32 linear = (screenSpace * position).x;
33 }
34 )";
35
36 static const char kTestFragmentShaderSource[] = R"(
37 precision mediump float;
38 void main() {
39 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
40 }
41 )";
42
43 struct GlShaderState {
44 GLenum type;
45 GLboolean deleteStatus;
46 GLboolean compileStatus;
47 GLint infoLogLength;
48 std::vector<GLchar> infoLog;
49 GLint sourceLength;
50 std::string source;
51 };
52
53 // SnapshotGlShaderTest - A helper class for testing snapshot's preservation of
54 // a GL shader object's states.
55 //
56 // It operates like SnapshotPreserveTest, and also holds information about a
57 // particular shader object which is manipulated in tests using
58 // SnapshotGlShaderTest as a fixture.
59 // Helper functions like loadSource first need a created shader identified by
60 // |m_shader_name|. This creation happens by default in stateChange. Use them in
61 // a lambda, set through setShaderStateChanger, to set up state without
62 // overriding doCheckedSnapshot.
63 //
64 class SnapshotGlShaderTest : public SnapshotPreserveTest {
65 public:
defaultStateCheck()66 void defaultStateCheck() override {
67 EXPECT_EQ(GL_FALSE, gl->glIsShader(m_shader_name));
68 }
69
changedStateCheck()70 void changedStateCheck() override {
71 SCOPED_TRACE("for shader " + std::to_string(m_shader_name));
72
73 EXPECT_TRUE(compareParameter(GL_SHADER_TYPE, m_shader_state.type));
74 EXPECT_TRUE(compareParameter(GL_DELETE_STATUS,
75 m_shader_state.deleteStatus));
76 EXPECT_TRUE(compareParameter(GL_COMPILE_STATUS,
77 m_shader_state.compileStatus));
78 EXPECT_TRUE(compareParameter(GL_INFO_LOG_LENGTH,
79 m_shader_state.infoLogLength));
80 EXPECT_TRUE(compareParameter(GL_SHADER_SOURCE_LENGTH,
81 m_shader_state.sourceLength));
82
83 std::vector<GLchar> srcData = {};
84 srcData.resize(m_shader_state.sourceLength);
85 gl->glGetShaderSource(m_shader_name, m_shader_state.sourceLength,
86 nullptr, srcData.data());
87 if (srcData.data() == NULL) {
88 EXPECT_EQ(0, m_shader_state.source.length()) << "source is empty";
89 } else {
90 EXPECT_STREQ(m_shader_state.source.c_str(), srcData.data());
91 }
92
93 std::vector<GLchar> infoLogData = {};
94 infoLogData.resize(m_shader_state.infoLogLength);
95 gl->glGetShaderInfoLog(m_shader_name, m_shader_state.infoLogLength,
96 nullptr, infoLogData.data());
97 if (infoLogData.data() == NULL) {
98 EXPECT_EQ(0, m_shader_state.infoLogLength) << "info log is empty";
99 } else {
100 EXPECT_STREQ(m_shader_state.infoLog.data(), infoLogData.data());
101 }
102 }
103
stateChange()104 void stateChange() override {
105 m_shader_name = gl->glCreateShader(m_shader_state.type);
106 m_shader_state_changer();
107
108 // Store state of info log
109 gl->glGetShaderiv(m_shader_name, GL_INFO_LOG_LENGTH,
110 &m_shader_state.infoLogLength);
111 m_shader_state.infoLog.resize(m_shader_state.infoLogLength);
112 gl->glGetShaderInfoLog(m_shader_name, m_shader_state.infoLogLength,
113 nullptr, m_shader_state.infoLog.data());
114 }
115
loadSource(const std::string & sourceString)116 void loadSource(const std::string& sourceString) {
117 GLboolean compiler;
118 gl->glGetBooleanv(GL_SHADER_COMPILER, &compiler);
119 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
120 if (compiler == GL_FALSE) {
121 fprintf(stderr, "Shader compiler is not supported.\n");
122 return;
123 }
124
125 if (m_shader_name == 0) {
126 FAIL() << "Cannot set source without a shader name";
127 }
128 m_shader_state.source = sourceString;
129 GLint len = sourceString.length();
130 if (len > 0) {
131 m_shader_state.sourceLength =
132 len + 1; // Counts the null terminator
133 }
134 const char* source = sourceString.c_str();
135 const char** sources = &source;
136 gl->glShaderSource(m_shader_name, 1, sources, &len);
137 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
138 }
139
compile(GLboolean expectCompileStatus=GL_TRUE)140 void compile(GLboolean expectCompileStatus = GL_TRUE) {
141 GLboolean compiler;
142 gl->glGetBooleanv(GL_SHADER_COMPILER, &compiler);
143 if (compiler == GL_FALSE) {
144 fprintf(stderr, "Shader compiler is not supported.\n");
145 return;
146 }
147
148 if (m_shader_name == 0) {
149 ADD_FAILURE() << "Cannot compile shader without a shader name";
150 }
151 if (m_shader_state.source.length() == 0) {
152 ADD_FAILURE() << "Shader needs source to compile";
153 }
154 gl->glCompileShader(m_shader_name);
155 m_shader_state.compileStatus = expectCompileStatus;
156 }
157
158 // Supply a lambda as |changer| to perform additional state setup after the
159 // shader has been created but before the snapshot is performed.
setShaderStateChanger(std::function<void ()> changer)160 void setShaderStateChanger(std::function<void()> changer) {
161 m_shader_state_changer = changer;
162 }
163
164 protected:
compareParameter(GLenum paramName,GLenum expected)165 testing::AssertionResult compareParameter(GLenum paramName,
166 GLenum expected) {
167 GLint value;
168 gl->glGetShaderiv(m_shader_name, paramName, &value);
169 EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
170 return compareValue<GLint>(
171 expected, value,
172 "mismatch on parameter " + describeGlEnum(paramName) +
173 " for shader " + std::to_string(m_shader_name));
174 }
175
176 GlShaderState m_shader_state = {};
177 GLuint m_shader_name;
__anona7bda7bb0102null178 std::function<void()> m_shader_state_changer = [] {};
179 };
180
181 class SnapshotGlVertexShaderTest : public SnapshotGlShaderTest {
182 public:
SnapshotGlVertexShaderTest()183 SnapshotGlVertexShaderTest() { m_shader_state = {GL_VERTEX_SHADER}; }
184 };
185
TEST_F(SnapshotGlVertexShaderTest,Create)186 TEST_F(SnapshotGlVertexShaderTest, Create) {
187 doCheckedSnapshot();
188 }
189
TEST_F(SnapshotGlVertexShaderTest,SetSource)190 TEST_F(SnapshotGlVertexShaderTest, SetSource) {
191 setShaderStateChanger(
192 [this] { loadSource(std::string(kTestVertexShaderSource)); });
193 doCheckedSnapshot();
194 }
195
TEST_F(SnapshotGlVertexShaderTest,CompileSuccess)196 TEST_F(SnapshotGlVertexShaderTest, CompileSuccess) {
197 setShaderStateChanger([this] {
198 loadSource(std::string(kTestVertexShaderSource));
199 compile();
200 });
201 doCheckedSnapshot();
202 }
203
TEST_F(SnapshotGlVertexShaderTest,CompileFail)204 TEST_F(SnapshotGlVertexShaderTest, CompileFail) {
205 std::string failedShader = "vec3 hi my name is compile failed";
206 setShaderStateChanger([this, &failedShader] {
207 loadSource(failedShader);
208 compile(GL_FALSE);
209 });
210 doCheckedSnapshot();
211 }
212
213 class SnapshotGlFragmentShaderTest : public SnapshotGlShaderTest {
214 public:
SnapshotGlFragmentShaderTest()215 SnapshotGlFragmentShaderTest() { m_shader_state = {GL_FRAGMENT_SHADER}; }
216 };
217
TEST_F(SnapshotGlFragmentShaderTest,Create)218 TEST_F(SnapshotGlFragmentShaderTest, Create) {
219 doCheckedSnapshot();
220 }
221
TEST_F(SnapshotGlFragmentShaderTest,SetSource)222 TEST_F(SnapshotGlFragmentShaderTest, SetSource) {
223 setShaderStateChanger(
224 [this] { loadSource(std::string(kTestFragmentShaderSource)); });
225 doCheckedSnapshot();
226 }
227
TEST_F(SnapshotGlFragmentShaderTest,CompileSuccess)228 TEST_F(SnapshotGlFragmentShaderTest, CompileSuccess) {
229 setShaderStateChanger([this] {
230 loadSource(std::string(kTestFragmentShaderSource));
231 compile();
232 });
233 doCheckedSnapshot();
234 }
235
TEST_F(SnapshotGlFragmentShaderTest,CompileFail)236 TEST_F(SnapshotGlFragmentShaderTest, CompileFail) {
237 std::string failedShader = "vec3 nice to meet you compile failed";
238 setShaderStateChanger([this, &failedShader] {
239 loadSource(failedShader);
240 compile(GL_FALSE);
241 });
242 doCheckedSnapshot();
243 }
244
245 } // namespace emugl
246