• 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 "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