1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // DifferentStencilMasksTest:
7 //   Tests the equality between stencilWriteMask and stencilBackWriteMask.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 
12 using namespace angle;
13 
14 namespace
15 {
16 class DifferentStencilMasksTest : public ANGLETest
17 {
18   protected:
DifferentStencilMasksTest()19     DifferentStencilMasksTest() : mProgram(0)
20     {
21         setWindowWidth(128);
22         setWindowHeight(128);
23         setConfigRedBits(8);
24         setConfigGreenBits(8);
25         setConfigBlueBits(8);
26         setConfigAlphaBits(8);
27         setConfigDepthBits(24);
28         setConfigStencilBits(8);
29     }
30 
SetUp()31     void SetUp() override
32     {
33         ANGLETest::SetUp();
34 
35         const std::string vertexShaderSource = SHADER_SOURCE
36         (
37             precision highp float;
38             attribute vec4 position;
39 
40             void main()
41             {
42                 gl_Position = position;
43             }
44         );
45 
46         const std::string fragmentShaderSource = SHADER_SOURCE
47         (
48             precision highp float;
49 
50             void main()
51             {
52                 gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
53             }
54         );
55 
56         mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
57         ASSERT_NE(0u, mProgram);
58 
59         glEnable(GL_STENCIL_TEST);
60         ASSERT_GL_NO_ERROR();
61     }
62 
TearDown()63     void TearDown() override
64     {
65         glDisable(GL_STENCIL_TEST);
66         if (mProgram != 0)
67             glDeleteProgram(mProgram);
68 
69         ANGLETest::TearDown();
70     }
71 
72     GLuint mProgram;
73 };
74 
75 // Tests that effectively same front and back masks are legal.
TEST_P(DifferentStencilMasksTest,DrawWithSameEffectiveMask)76 TEST_P(DifferentStencilMasksTest, DrawWithSameEffectiveMask)
77 {
78     // 0x00ff and 0x01ff are effectively 0x00ff by being masked by the current stencil bits, 8.
79     glStencilMaskSeparate(GL_FRONT, 0x00ff);
80     glStencilMaskSeparate(GL_BACK, 0x01ff);
81 
82     glUseProgram(mProgram);
83 
84     drawQuad(mProgram, "position", 0.5f);
85 
86     EXPECT_GL_NO_ERROR();
87 }
88 
89 // Tests that effectively different front and back masks are illegal.
TEST_P(DifferentStencilMasksTest,DrawWithDifferentMask)90 TEST_P(DifferentStencilMasksTest, DrawWithDifferentMask)
91 {
92     glStencilMaskSeparate(GL_FRONT, 0x0001);
93     glStencilMaskSeparate(GL_BACK, 0x0002);
94 
95     glUseProgram(mProgram);
96 
97     drawQuad(mProgram, "position", 0.5f);
98 
99     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
100 }
101 
102 class DifferentStencilMasksWithoutStencilBufferTest : public ANGLETest
103 {
104   protected:
DifferentStencilMasksWithoutStencilBufferTest()105     DifferentStencilMasksWithoutStencilBufferTest() : mProgram(0)
106     {
107         setWindowWidth(128);
108         setWindowHeight(128);
109         setConfigRedBits(8);
110         setConfigGreenBits(8);
111         setConfigBlueBits(8);
112         setConfigAlphaBits(8);
113         setConfigDepthBits(0);
114         setConfigStencilBits(0);
115     }
116 
SetUp()117     void SetUp() override
118     {
119         ANGLETest::SetUp();
120 
121         const std::string vertexShaderSource = SHADER_SOURCE
122         (
123             precision highp float;
124             attribute vec4 position;
125 
126             void main()
127             {
128                 gl_Position = position;
129             }
130         );
131 
132         const std::string fragmentShaderSource = SHADER_SOURCE
133         (
134             precision highp float;
135 
136             void main()
137             {
138                 gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
139             }
140         );
141 
142         mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
143         ASSERT_NE(0u, mProgram);
144 
145         glEnable(GL_STENCIL_TEST);
146         ASSERT_GL_NO_ERROR();
147     }
148 
TearDown()149     void TearDown() override
150     {
151         glDisable(GL_STENCIL_TEST);
152         if (mProgram != 0)
153             glDeleteProgram(mProgram);
154 
155         ANGLETest::TearDown();
156     }
157 
158     GLuint mProgram;
159 };
160 
161 // Tests that effectively different front and back masks, without stencil bits, are legal.
TEST_P(DifferentStencilMasksWithoutStencilBufferTest,DrawWithDifferentMask)162 TEST_P(DifferentStencilMasksWithoutStencilBufferTest, DrawWithDifferentMask)
163 {
164     glStencilMaskSeparate(GL_FRONT, 0x0001);
165     glStencilMaskSeparate(GL_BACK, 0x0002);
166 
167     glUseProgram(mProgram);
168 
169     drawQuad(mProgram, "position", 0.5f);
170 
171     EXPECT_GL_NO_ERROR();
172 }
173 
174 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
175 // tests should be run against.
176 ANGLE_INSTANTIATE_TEST(DifferentStencilMasksTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL());
177 ANGLE_INSTANTIATE_TEST(DifferentStencilMasksWithoutStencilBufferTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL());
178 } // anonymous namespace
179