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 #include "OpenGLTestContext.h"
17 
18 #include <gtest/gtest.h>
19 #include <array>
20 
21 namespace gfxstream {
22 namespace gl {
23 namespace {
24 
25 struct GlStencilFunc {
26     GLenum func;
27     GLint ref;
28     GLuint mask;
29 };
30 
31 struct GlStencilOp {
32     GLenum sfail;
33     GLenum dpfail;
34     GLenum dppass;
35 };
36 
37 struct GlBlendFunc {
38     GLenum srcRGB;
39     GLenum dstRGB;
40     GLenum srcAlpha;
41     GLenum dstAlpha;
42 };
43 
44 struct GlWriteMask {
45     GLboolean colorMaskR;
46     GLboolean colorMaskG;
47     GLboolean colorMaskB;
48     GLboolean colorMaskA;
49 };
50 
51 static const int kTestMaxDrawBuffers = 8;
52 
53 typedef std::array<GlWriteMask, kTestMaxDrawBuffers> GlWriteMaskArray;
54 typedef std::array<GlBlendFunc, kTestMaxDrawBuffers> GlBlendFuncArray;
55 
56 static constexpr GlWriteMaskArray kGLES2TestWriteMaski {{
57           {GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE},
58           {GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE},
59           {GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE},
60           {GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE},
61           {GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE},
62           {GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE},
63           {GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE},
64           {GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE}
65 }};
66 
67 static constexpr GlBlendFuncArray kGLES2TestBlendFunci {{
68           {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR},
69           {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA},
70           {GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA},
71           {GL_SRC_ALPHA_SATURATE, GL_ONE, GL_SRC_ALPHA_SATURATE, GL_ONE},
72           {GL_ONE_MINUS_SRC_COLOR, GL_SRC_COLOR, GL_ONE_MINUS_DST_COLOR, GL_DST_COLOR},
73           {GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_SRC_COLOR, GL_SRC_COLOR},
74           {GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_ALPHA, GL_CONSTANT_ALPHA},
75           {GL_ONE, GL_SRC_ALPHA_SATURATE, GL_ONE, GL_SRC_ALPHA_SATURATE},
76 }};
77 
78 // Scissor box settings to attempt
79 static const std::vector<GLint> kGLES2TestScissorBox = {2, 3, 10, 20};
80 
81 // Default stencil operation modes
82 static const GlStencilOp kGLES2DefaultStencilOp = {GL_KEEP, GL_KEEP, GL_KEEP};
83 
84 // Stencil reference value to attempt
85 static const GLint kGLES2TestStencilRef = 1;
86 
87 // Stencil mask values to attempt
88 static const GLuint kGLES2TestStencilMasks[] = {0, 1, 0x1000000, 0x7FFFFFFF};
89 
90 // Blend function settings to attempt
91 static const GlBlendFunc kGLES2TestBlendFuncs[] = {
92         {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR,
93          GL_ONE_MINUS_DST_COLOR},
94         {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
95          GL_ONE_MINUS_DST_ALPHA},
96         {GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA,
97          GL_ONE_MINUS_CONSTANT_ALPHA},
98         {GL_SRC_ALPHA_SATURATE, GL_ONE, GL_SRC_ALPHA_SATURATE, GL_ONE}};
99 
100 class SnapshotGlScissorBoxTest
101     : public SnapshotSetValueTest<std::vector<GLint>>,
102       public ::testing::WithParamInterface<std::vector<GLint>> {
stateCheck(std::vector<GLint> expected)103     void stateCheck(std::vector<GLint> expected) override {
104         EXPECT_TRUE(compareGlobalGlIntv(gl, GL_SCISSOR_BOX, expected));
105     }
stateChange()106     void stateChange() override {
107         gl->glScissor(GetParam()[0], GetParam()[1], GetParam()[2],
108                       GetParam()[3]);
109     }
110 };
111 
TEST_P(SnapshotGlScissorBoxTest,SetScissorBox)112 TEST_P(SnapshotGlScissorBoxTest, SetScissorBox) {
113     // different drivers act differently; get the default scissorbox
114     std::vector<GLint> defaultBox;
115     defaultBox.resize(4);
116     gl->glGetIntegerv(GL_SCISSOR_BOX, &defaultBox[0]);
117     EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
118 
119     setExpectedValues(defaultBox, GetParam());
120     doCheckedSnapshot();
121 }
122 
123 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
124                          SnapshotGlScissorBoxTest,
125                          ::testing::Values(kGLES2TestScissorBox));
126 
127 // Tests preservation of stencil test conditional state, set by glStencilFunc.
128 class SnapshotGlStencilConditionsTest
129     : public SnapshotSetValueTest<GlStencilFunc> {
stateCheck(GlStencilFunc expected)130     void stateCheck(GlStencilFunc expected) override {
131         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_FUNC, expected.func));
132         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_REF, expected.ref));
133         EXPECT_TRUE(
134                 compareGlobalGlInt(gl, GL_STENCIL_VALUE_MASK, expected.mask));
135         EXPECT_TRUE(
136                 compareGlobalGlInt(gl, GL_STENCIL_BACK_FUNC, expected.func));
137         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_REF, expected.ref));
138         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_VALUE_MASK,
139                                        expected.mask));
140     }
stateChange()141     void stateChange() override {
142         GlStencilFunc sFunc = *m_changed_value;
143         gl->glStencilFunc(sFunc.func, sFunc.ref, sFunc.mask);
144     }
145 };
146 
147 class SnapshotGlStencilFuncTest : public SnapshotGlStencilConditionsTest,
148                                   public ::testing::WithParamInterface<GLenum> {
149 };
150 
151 class SnapshotGlStencilMaskTest : public SnapshotGlStencilConditionsTest,
152                                   public ::testing::WithParamInterface<GLuint> {
153 };
154 
TEST_P(SnapshotGlStencilFuncTest,SetStencilFunc)155 TEST_P(SnapshotGlStencilFuncTest, SetStencilFunc) {
156     // different drivers act differently; get the default mask
157     GLint defaultStencilMask;
158     gl->glGetIntegerv(GL_STENCIL_VALUE_MASK, &defaultStencilMask);
159     EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
160 
161     GlStencilFunc defaultStencilFunc = {GL_ALWAYS, 0,
162                                         (GLuint)defaultStencilMask};
163     GlStencilFunc testStencilFunc = {GetParam(), kGLES2TestStencilRef, 0};
164     setExpectedValues(defaultStencilFunc, testStencilFunc);
165     doCheckedSnapshot();
166 }
167 
TEST_P(SnapshotGlStencilMaskTest,SetStencilMask)168 TEST_P(SnapshotGlStencilMaskTest, SetStencilMask) {
169     // different drivers act differently; get the default mask
170     GLint defaultStencilMask;
171     gl->glGetIntegerv(GL_STENCIL_VALUE_MASK, &defaultStencilMask);
172     EXPECT_EQ(GL_NO_ERROR, gl->glGetError());
173 
174     GlStencilFunc defaultStencilFunc = {GL_ALWAYS, 0,
175                                         (GLuint)defaultStencilMask};
176     GlStencilFunc testStencilFunc = {GL_ALWAYS, kGLES2TestStencilRef,
177                                      GetParam()};
178     setExpectedValues(defaultStencilFunc, testStencilFunc);
179     doCheckedSnapshot();
180 }
181 
182 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
183                          SnapshotGlStencilFuncTest,
184                          ::testing::ValuesIn(kGLES2StencilFuncs));
185 
186 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
187                          SnapshotGlStencilMaskTest,
188                          ::testing::ValuesIn(kGLES2TestStencilMasks));
189 
190 class SnapshotGlStencilConsequenceTest
191     : public SnapshotSetValueTest<GlStencilOp> {
stateCheck(GlStencilOp expected)192     void stateCheck(GlStencilOp expected) override {
193         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_FAIL, expected.sfail));
194         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_PASS_DEPTH_FAIL,
195                                        expected.dpfail));
196         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_PASS_DEPTH_PASS,
197                                        expected.dppass));
198         EXPECT_TRUE(
199                 compareGlobalGlInt(gl, GL_STENCIL_BACK_FAIL, expected.sfail));
200         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_PASS_DEPTH_FAIL,
201                                        expected.dpfail));
202         EXPECT_TRUE(compareGlobalGlInt(gl, GL_STENCIL_BACK_PASS_DEPTH_PASS,
203                                        expected.dppass));
204     }
stateChange()205     void stateChange() override {
206         GlStencilOp sOp = *m_changed_value;
207         gl->glStencilOp(sOp.sfail, sOp.dpfail, sOp.dppass);
208     }
209 };
210 
211 class SnapshotGlStencilFailTest : public SnapshotGlStencilConsequenceTest,
212                                   public ::testing::WithParamInterface<GLenum> {
213 };
214 
215 class SnapshotGlStencilDepthFailTest
216     : public SnapshotGlStencilConsequenceTest,
217       public ::testing::WithParamInterface<GLenum> {};
218 
219 class SnapshotGlStencilDepthPassTest
220     : public SnapshotGlStencilConsequenceTest,
221       public ::testing::WithParamInterface<GLenum> {};
222 
TEST_P(SnapshotGlStencilFailTest,SetStencilOps)223 TEST_P(SnapshotGlStencilFailTest, SetStencilOps) {
224     GlStencilOp testStencilOp = {GetParam(), GL_KEEP, GL_KEEP};
225     setExpectedValues(kGLES2DefaultStencilOp, testStencilOp);
226     doCheckedSnapshot();
227 }
228 
TEST_P(SnapshotGlStencilDepthFailTest,SetStencilOps)229 TEST_P(SnapshotGlStencilDepthFailTest, SetStencilOps) {
230     GlStencilOp testStencilOp = {GL_KEEP, GetParam(), GL_KEEP};
231     setExpectedValues(kGLES2DefaultStencilOp, testStencilOp);
232     doCheckedSnapshot();
233 }
234 
TEST_P(SnapshotGlStencilDepthPassTest,SetStencilOps)235 TEST_P(SnapshotGlStencilDepthPassTest, SetStencilOps) {
236     GlStencilOp testStencilOp = {GL_KEEP, GL_KEEP, GetParam()};
237     setExpectedValues(kGLES2DefaultStencilOp, testStencilOp);
238     doCheckedSnapshot();
239 }
240 
241 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
242                          SnapshotGlStencilFailTest,
243                          ::testing::ValuesIn(kGLES2StencilOps));
244 
245 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
246                          SnapshotGlStencilDepthFailTest,
247                          ::testing::ValuesIn(kGLES2StencilOps));
248 
249 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
250                          SnapshotGlStencilDepthPassTest,
251                          ::testing::ValuesIn(kGLES2StencilOps));
252 
253 class SnapshotGlDepthFuncTest : public SnapshotSetValueTest<GLenum>,
254                                 public ::testing::WithParamInterface<GLenum> {
stateCheck(GLenum expected)255     void stateCheck(GLenum expected) override {
256         EXPECT_TRUE(compareGlobalGlInt(gl, GL_DEPTH_FUNC, expected));
257     }
stateChange()258     void stateChange() override { gl->glDepthFunc(*m_changed_value); }
259 };
260 
TEST_P(SnapshotGlDepthFuncTest,SetDepthFunc)261 TEST_P(SnapshotGlDepthFuncTest, SetDepthFunc) {
262     setExpectedValues(GL_LESS, GetParam());
263     doCheckedSnapshot();
264 }
265 
266 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
267                          SnapshotGlDepthFuncTest,
268                          ::testing::ValuesIn(kGLES2StencilFuncs));
269 
270 class SnapshotGlBlendEquationTest
271     : public SnapshotSetValueTest<GLenum>,
272       public ::testing::WithParamInterface<GLenum> {
stateCheck(GLenum expected)273     void stateCheck(GLenum expected) override {
274         EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_EQUATION_RGB, expected));
275         EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_EQUATION_ALPHA, expected));
276     }
stateChange()277     void stateChange() override { gl->glBlendEquation(*m_changed_value); }
278 };
279 
TEST_P(SnapshotGlBlendEquationTest,SetBlendEquation)280 TEST_P(SnapshotGlBlendEquationTest, SetBlendEquation) {
281     setExpectedValues(GL_FUNC_ADD, GetParam());
282     doCheckedSnapshot();
283 }
284 
285 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
286                          SnapshotGlBlendEquationTest,
287                          ::testing::ValuesIn(kGLES2BlendEquations));
288 
289 class SnapshotGlBlendFuncTest
290     : public SnapshotSetValueTest<GlBlendFunc>,
291       public ::testing::WithParamInterface<GlBlendFunc> {
stateCheck(GlBlendFunc expected)292     void stateCheck(GlBlendFunc expected) {
293         EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_SRC_RGB, expected.srcRGB));
294         EXPECT_TRUE(compareGlobalGlInt(gl, GL_BLEND_DST_RGB, expected.dstRGB));
295         EXPECT_TRUE(
296                 compareGlobalGlInt(gl, GL_BLEND_SRC_ALPHA, expected.srcAlpha));
297         EXPECT_TRUE(
298                 compareGlobalGlInt(gl, GL_BLEND_DST_ALPHA, expected.dstAlpha));
299     }
stateChange()300     void stateChange() {
301         GlBlendFunc target = *m_changed_value;
302         gl->glBlendFuncSeparate(target.srcRGB, target.dstRGB, target.srcAlpha,
303                                 target.dstAlpha);
304     }
305 };
306 
TEST_P(SnapshotGlBlendFuncTest,SetBlendFunc)307 TEST_P(SnapshotGlBlendFuncTest, SetBlendFunc) {
308     GlBlendFunc defaultBlendFunc = {.srcRGB = GL_ONE,
309                                     .dstRGB = GL_ZERO,
310                                     .srcAlpha = GL_ONE,
311                                     .dstAlpha = GL_ZERO};
312     setExpectedValues(defaultBlendFunc, GetParam());
313     doCheckedSnapshot();
314 }
315 
316 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps,
317                          SnapshotGlBlendFuncTest,
318                          ::testing::ValuesIn(kGLES2TestBlendFuncs));
319 
320 class SnapshotGlWriteMaskiTest
321     : public SnapshotSetValueTest<GlWriteMaskArray>,
322       public ::testing::WithParamInterface<GlWriteMaskArray> {
323 
stateCheck(GlWriteMaskArray expected)324     void stateCheck(GlWriteMaskArray expected) {
325         for(int i = 0 ; i < m_maxDrawBuffers ; ++i ) {
326            std::vector<GLboolean> res{expected[i].colorMaskR, expected[i].colorMaskG, expected[i].colorMaskB, expected[i].colorMaskA};
327            EXPECT_TRUE(compareGlobalGlBooleanv_i(gl, GL_COLOR_WRITEMASK, i, res, 4));
328         }
329     }
330 
stateChange()331     void stateChange() {
332         auto& writeMasks = *m_changed_value;
333         for(int i = 0 ; i < m_maxDrawBuffers ; ++i)
334           gl->glColorMaskiEXT(i,
335                               writeMasks[i].colorMaskR,
336                               writeMasks[i].colorMaskG,
337                               writeMasks[i].colorMaskB,
338                               writeMasks[i].colorMaskA);
339     }
340 
341   protected:
342     GLint m_maxDrawBuffers = 1;
343 };
344 
TEST_P(SnapshotGlWriteMaskiTest,ColorMaski)345 TEST_P(SnapshotGlWriteMaskiTest, ColorMaski) {
346     const std::string ext((const char*)gl->glGetString(GL_EXTENSIONS));
347     EMUGL_SKIP_TEST_IF(ext.find("GL_EXT_draw_buffers_indexed") == std::string::npos);
348     gl->glGetIntegerv(GL_MAX_DRAW_BUFFERS, &m_maxDrawBuffers);
349 
350     const GlWriteMaskArray defaultWriteMask { {
351         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
352         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
353         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
354         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
355         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
356         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
357         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
358         {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE},
359     } };
360     setExpectedValues(defaultWriteMask, GetParam());
361     doCheckedSnapshot();
362 }
363 
364 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps, SnapshotGlWriteMaskiTest,
365                         ::testing::Values(kGLES2TestWriteMaski));
366 
367 // test glBlendFunci load and restore
368 class SnapshotGlBlendFunciTest
369     : public SnapshotSetValueTest<GlBlendFuncArray>,
370       public ::testing::WithParamInterface<GlBlendFuncArray> {
371 
stateCheck(GlBlendFuncArray expected)372     void stateCheck(GlBlendFuncArray expected) {
373         for(int i = 0 ; i < m_maxDrawBuffers ; ++i ) {
374            EXPECT_TRUE(compareGlobalGlInt_i(gl, GL_BLEND_SRC_RGB, i, expected[i].srcRGB));
375            EXPECT_TRUE(compareGlobalGlInt_i(gl, GL_BLEND_DST_RGB, i, expected[i].dstRGB));
376            EXPECT_TRUE(compareGlobalGlInt_i(gl, GL_BLEND_SRC_ALPHA, i, expected[i].srcAlpha));
377            EXPECT_TRUE(compareGlobalGlInt_i(gl, GL_BLEND_DST_ALPHA, i, expected[i].dstAlpha));
378         }
379     }
380 
stateChange()381     void stateChange() {
382         auto& blendFuncs = *m_changed_value;
383         for(int i = 0 ; i < m_maxDrawBuffers ; ++i) {
384             gl->glBlendFuncSeparateiEXT(i, blendFuncs[i].srcRGB, blendFuncs[i].dstRGB, blendFuncs[i].srcAlpha,
385                                 blendFuncs[i].dstAlpha);
386         }
387     }
388 
389   protected:
390     GLint m_maxDrawBuffers = 1;
391 };
392 
TEST_P(SnapshotGlBlendFunciTest,BlendFunci)393 TEST_P(SnapshotGlBlendFunciTest, BlendFunci) {
394     const std::string ext((const char*)gl->glGetString(GL_EXTENSIONS));
395     EMUGL_SKIP_TEST_IF(ext.find("GL_EXT_draw_buffers_indexed") == std::string::npos);
396     gl->glGetIntegerv(GL_MAX_DRAW_BUFFERS, &m_maxDrawBuffers);
397 
398     const GlBlendFuncArray defaultBlendFunc { {
399         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
400         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
401         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
402         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
403         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
404         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
405         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
406         {GL_ONE, GL_ZERO, GL_ONE, GL_ZERO},
407     } };
408     setExpectedValues(defaultBlendFunc, GetParam());
409     doCheckedSnapshot();
410 }
411 
412 INSTANTIATE_TEST_SUITE_P(GLES2SnapshotPixelOps, SnapshotGlBlendFunciTest,
413                         ::testing::Values(kGLES2TestBlendFunci));
414 
415 }  // namespace
416 }  // namespace gl
417 }  // namespace gfxstream
418