1 //
2 // Copyright 2018 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 // DepthStencilTest:
7 // Tests covering depth- or stencil-only rendering to make sure the other non-existing aspect is
8 // not affecting the results (since the format may be emulated with one that has both aspects).
9 //
10
11 #include "test_utils/ANGLETest.h"
12
13 #include "platform/FeaturesVk.h"
14 #include "test_utils/gl_raii.h"
15
16 using namespace angle;
17
18 namespace
19 {
20
21 class DepthStencilTest : public ANGLETest
22 {
23 protected:
DepthStencilTest()24 DepthStencilTest()
25 {
26 setWindowWidth(128);
27 setWindowHeight(128);
28 setConfigRedBits(8);
29 setConfigGreenBits(8);
30 setConfigBlueBits(8);
31 setConfigAlphaBits(8);
32 setConfigDepthBits(24);
33 setConfigStencilBits(8);
34 }
35
testSetUp()36 void testSetUp() override
37 {
38 glBindTexture(GL_TEXTURE_2D, mColorTexture);
39 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
40 GL_UNSIGNED_BYTE, nullptr);
41
42 // Setup Color/Stencil FBO with a stencil format that's emulated with packed depth/stencil.
43 glBindFramebuffer(GL_FRAMEBUFFER, mColorStencilFBO);
44
45 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture,
46 0);
47 glBindRenderbuffer(GL_RENDERBUFFER, mStencilTexture);
48 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(),
49 getWindowHeight());
50 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
51 mStencilTexture);
52
53 ASSERT_GL_NO_ERROR();
54
55 // Note: GL_DEPTH_COMPONENT24 is allowed in GLES2 with GL_OES_depth24 extension.
56 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_OES_depth24"))
57 {
58 // Setup Color/Depth FBO with a depth format that's emulated with packed depth/stencil.
59 glBindFramebuffer(GL_FRAMEBUFFER, mColorDepthFBO);
60
61 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
62 mColorTexture, 0);
63 glBindRenderbuffer(GL_RENDERBUFFER, mDepthTexture);
64 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, getWindowWidth(),
65 getWindowHeight());
66 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
67 mDepthTexture);
68 }
69
70 ASSERT_GL_NO_ERROR();
71 }
72
bindColorStencilFBO()73 void bindColorStencilFBO()
74 {
75 glBindFramebuffer(GL_FRAMEBUFFER, mColorStencilFBO);
76 mHasDepth = false;
77 }
78
bindColorDepthFBO()79 void bindColorDepthFBO()
80 {
81 glBindFramebuffer(GL_FRAMEBUFFER, mColorDepthFBO);
82 mHasStencil = false;
83 }
84
85 // Override a feature to force emulation of stencil-only and depth-only formats with a packed
86 // depth/stencil format
overrideFeaturesVk(FeaturesVk * featuresVk)87 void overrideFeaturesVk(FeaturesVk *featuresVk) override
88 {
89 featuresVk->overrideFeatures({"force_fallback_format"}, true);
90 }
91
92 void prepareSingleEmulatedWithPacked();
93 void ensureColor(GLColor color);
94 void ensureDepthUnaffected();
95 void ensureStencilUnaffected();
96
97 private:
98 GLFramebuffer mColorStencilFBO;
99 GLFramebuffer mColorDepthFBO;
100 GLTexture mColorTexture;
101 GLRenderbuffer mDepthTexture;
102 GLRenderbuffer mStencilTexture;
103
104 bool mHasDepth = true;
105 bool mHasStencil = true;
106 };
107
ensureColor(GLColor color)108 void DepthStencilTest::ensureColor(GLColor color)
109 {
110 const int width = getWindowWidth();
111 const int height = getWindowHeight();
112
113 std::vector<GLColor> pixelData(width * height);
114 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
115
116 for (int i = 0; i < width * height; i += 16)
117 {
118 GLColor actualColor = pixelData[i];
119 EXPECT_NEAR(color.R, actualColor.R, 1);
120 EXPECT_NEAR(color.G, actualColor.G, 1);
121 EXPECT_NEAR(color.B, actualColor.B, 1);
122 EXPECT_NEAR(color.A, actualColor.A, 1);
123
124 if (i % width == 0)
125 i += 16 * width;
126 }
127 }
128
ensureDepthUnaffected()129 void DepthStencilTest::ensureDepthUnaffected()
130 {
131 ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
132 glEnable(GL_DEPTH_TEST);
133 glDepthFunc(GL_EQUAL);
134 drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), 0.123f);
135 glDisable(GL_DEPTH_TEST);
136 ASSERT_GL_NO_ERROR();
137
138 // Since depth shouldn't exist, the drawQuad above should succeed in turning the whole image
139 // blue.
140 ensureColor(GLColor::blue);
141 }
142
ensureStencilUnaffected()143 void DepthStencilTest::ensureStencilUnaffected()
144 {
145 ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
146 essl1_shaders::fs::Green());
147 glEnable(GL_STENCIL_TEST);
148 glStencilFunc(GL_EQUAL, 0x1B, 0xFF);
149 drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
150 glDisable(GL_STENCIL_TEST);
151 ASSERT_GL_NO_ERROR();
152
153 // Since stencil shouldn't exist, the drawQuad above should succeed in turning the whole image
154 // green.
155 ensureColor(GLColor::green);
156 }
157
prepareSingleEmulatedWithPacked()158 void DepthStencilTest::prepareSingleEmulatedWithPacked()
159 {
160 const int w = getWindowWidth();
161 const int h = getWindowHeight();
162 const int whalf = w >> 1;
163 const int hhalf = h >> 1;
164
165 // Clear to a random color, 0.75 depth and 0x36 stencil
166 Vector4 color1(0.1f, 0.2f, 0.3f, 0.4f);
167 GLColor color1RGB(color1);
168
169 glClearColor(color1[0], color1[1], color1[2], color1[3]);
170 glClearDepthf(0.75f);
171 glClearStencil(0x36);
172 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
173 ASSERT_GL_NO_ERROR();
174
175 // Verify color was cleared correctly.
176 EXPECT_PIXEL_COLOR_NEAR(0, 0, color1RGB, 1);
177
178 // Use masked color to clear two channels of the image to a second color, 0.25 depth and 0x59
179 // stencil.
180 Vector4 color2(0.2f, 0.4f, 0.6f, 0.8f);
181 glClearColor(color2[0], color2[1], color2[2], color2[3]);
182 glClearDepthf(0.25f);
183 glClearStencil(0x59);
184 glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE);
185 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
186 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
187 ASSERT_GL_NO_ERROR();
188
189 GLColor color2RGB(Vector4(color2[0], color1[1], color2[2], color1[3]));
190
191 EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color2RGB, 1);
192
193 EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
194 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
195 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
196 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
197
198 // Use scissor to clear the center to a third color, 0.5 depth and 0xA9 stencil.
199 glEnable(GL_SCISSOR_TEST);
200 glScissor(whalf / 2, hhalf / 2, whalf, hhalf);
201
202 Vector4 color3(0.3f, 0.5f, 0.7f, 0.9f);
203 GLColor color3RGB(color3);
204 glClearColor(color3[0], color3[1], color3[2], color3[3]);
205 glClearDepthf(0.5f);
206 glClearStencil(0xA9);
207 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
208 glDisable(GL_SCISSOR_TEST);
209 ASSERT_GL_NO_ERROR();
210
211 EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color3RGB, 1);
212
213 EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
214 EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
215 EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
216 EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
217
218 // Use scissor to draw to the right half of the image with a fourth color, 0.6 depth and 0x84
219 // stencil.
220 glEnable(GL_SCISSOR_TEST);
221 glScissor(whalf, 0, whalf, h);
222
223 ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
224 glEnable(GL_STENCIL_TEST);
225 glStencilFunc(GL_ALWAYS, 0x84, 0xFF);
226 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
227 glStencilMask(0xFF);
228 drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.2f);
229
230 glDisable(GL_STENCIL_TEST);
231 glDisable(GL_SCISSOR_TEST);
232 }
233
234 // Tests that clearing or rendering into a depth-only format doesn't affect stencil.
TEST_P(DepthStencilTest,DepthOnlyEmulatedWithPacked)235 TEST_P(DepthStencilTest, DepthOnlyEmulatedWithPacked)
236 {
237 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_depth24"));
238
239 bindColorDepthFBO();
240 prepareSingleEmulatedWithPacked();
241 ensureStencilUnaffected();
242 }
243
244 // Tests that clearing or rendering into a stencil-only format doesn't affect depth.
TEST_P(DepthStencilTest,StencilOnlyEmulatedWithPacked)245 TEST_P(DepthStencilTest, StencilOnlyEmulatedWithPacked)
246 {
247 // http://anglebug.com/4092
248 ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D9());
249 bindColorStencilFBO();
250 prepareSingleEmulatedWithPacked();
251 ensureDepthUnaffected();
252 }
253
254 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DepthStencilTest);
255
256 } // anonymous namespace
257