• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
108 class DepthStencilTestES3 : public DepthStencilTest
109 {
110   protected:
111     void compareDepth(uint32_t expected);
112     void clearAndCompareDepth(GLfloat depth, uint32_t expected);
113     void drawAndCompareDepth(GLProgram &program, GLfloat depth, uint32_t expected);
114 };
115 
ensureColor(GLColor color)116 void DepthStencilTest::ensureColor(GLColor color)
117 {
118     const int width  = getWindowWidth();
119     const int height = getWindowHeight();
120 
121     std::vector<GLColor> pixelData(width * height);
122     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data());
123 
124     for (int i = 0; i < width * height; i += 16)
125     {
126         GLColor actualColor = pixelData[i];
127         EXPECT_NEAR(color.R, actualColor.R, 1);
128         EXPECT_NEAR(color.G, actualColor.G, 1);
129         EXPECT_NEAR(color.B, actualColor.B, 1);
130         EXPECT_NEAR(color.A, actualColor.A, 1);
131 
132         if (i % width == 0)
133             i += 16 * width;
134     }
135 }
136 
ensureDepthUnaffected()137 void DepthStencilTest::ensureDepthUnaffected()
138 {
139     ANGLE_GL_PROGRAM(depthTestProgram, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
140     glEnable(GL_DEPTH_TEST);
141     glDepthFunc(GL_EQUAL);
142     drawQuad(depthTestProgram, essl1_shaders::PositionAttrib(), 0.123f);
143     glDisable(GL_DEPTH_TEST);
144     ASSERT_GL_NO_ERROR();
145 
146     // Since depth shouldn't exist, the drawQuad above should succeed in turning the whole image
147     // blue.
148     ensureColor(GLColor::blue);
149 }
150 
ensureStencilUnaffected()151 void DepthStencilTest::ensureStencilUnaffected()
152 {
153     ANGLE_GL_PROGRAM(stencilTestProgram, essl1_shaders::vs::Passthrough(),
154                      essl1_shaders::fs::Green());
155     glEnable(GL_STENCIL_TEST);
156     glStencilFunc(GL_EQUAL, 0x1B, 0xFF);
157     drawQuad(stencilTestProgram, essl1_shaders::PositionAttrib(), 0.0f);
158     glDisable(GL_STENCIL_TEST);
159     ASSERT_GL_NO_ERROR();
160 
161     // Since stencil shouldn't exist, the drawQuad above should succeed in turning the whole image
162     // green.
163     ensureColor(GLColor::green);
164 }
165 
prepareSingleEmulatedWithPacked()166 void DepthStencilTest::prepareSingleEmulatedWithPacked()
167 {
168     const int w     = getWindowWidth();
169     const int h     = getWindowHeight();
170     const int whalf = w >> 1;
171     const int hhalf = h >> 1;
172 
173     // Clear to a random color, 0.75 depth and 0x36 stencil
174     Vector4 color1(0.1f, 0.2f, 0.3f, 0.4f);
175     GLColor color1RGB(color1);
176 
177     glClearColor(color1[0], color1[1], color1[2], color1[3]);
178     glClearDepthf(0.75f);
179     glClearStencil(0x36);
180     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
181     ASSERT_GL_NO_ERROR();
182 
183     // Verify color was cleared correctly.
184     EXPECT_PIXEL_COLOR_NEAR(0, 0, color1RGB, 1);
185 
186     // Use masked color to clear two channels of the image to a second color, 0.25 depth and 0x59
187     // stencil.
188     Vector4 color2(0.2f, 0.4f, 0.6f, 0.8f);
189     glClearColor(color2[0], color2[1], color2[2], color2[3]);
190     glClearDepthf(0.25f);
191     glClearStencil(0x59);
192     glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE);
193     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
194     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
195     ASSERT_GL_NO_ERROR();
196 
197     GLColor color2RGB(Vector4(color2[0], color1[1], color2[2], color1[3]));
198 
199     EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color2RGB, 1);
200 
201     EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
202     EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
203     EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
204     EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
205 
206     // Use scissor to clear the center to a third color, 0.5 depth and 0xA9 stencil.
207     glEnable(GL_SCISSOR_TEST);
208     glScissor(whalf / 2, hhalf / 2, whalf, hhalf);
209 
210     Vector4 color3(0.3f, 0.5f, 0.7f, 0.9f);
211     GLColor color3RGB(color3);
212     glClearColor(color3[0], color3[1], color3[2], color3[3]);
213     glClearDepthf(0.5f);
214     glClearStencil(0xA9);
215     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
216     glDisable(GL_SCISSOR_TEST);
217     ASSERT_GL_NO_ERROR();
218 
219     EXPECT_PIXEL_COLOR_NEAR(whalf, hhalf, color3RGB, 1);
220 
221     EXPECT_PIXEL_COLOR_NEAR(0, 0, color2RGB, 1);
222     EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, color2RGB, 1);
223     EXPECT_PIXEL_COLOR_NEAR(0, h - 1, color2RGB, 1);
224     EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, color2RGB, 1);
225 
226     // Use scissor to draw to the right half of the image with a fourth color, 0.6 depth and 0x84
227     // stencil.
228     glEnable(GL_SCISSOR_TEST);
229     glScissor(whalf, 0, whalf, h);
230 
231     ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
232     glEnable(GL_STENCIL_TEST);
233     glStencilFunc(GL_ALWAYS, 0x84, 0xFF);
234     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
235     glStencilMask(0xFF);
236     drawQuad(redProgram, essl1_shaders::PositionAttrib(), 0.2f);
237 
238     glDisable(GL_STENCIL_TEST);
239     glDisable(GL_SCISSOR_TEST);
240 }
241 
242 // Tests that clearing or rendering into a depth-only format doesn't affect stencil.
TEST_P(DepthStencilTest,DepthOnlyEmulatedWithPacked)243 TEST_P(DepthStencilTest, DepthOnlyEmulatedWithPacked)
244 {
245     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_depth24"));
246 
247     bindColorDepthFBO();
248     prepareSingleEmulatedWithPacked();
249     ensureStencilUnaffected();
250 }
251 
252 // Tests that clearing or rendering into a stencil-only format doesn't affect depth.
TEST_P(DepthStencilTest,StencilOnlyEmulatedWithPacked)253 TEST_P(DepthStencilTest, StencilOnlyEmulatedWithPacked)
254 {
255     // http://anglebug.com/4092
256     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D9());
257     bindColorStencilFBO();
258     prepareSingleEmulatedWithPacked();
259     ensureDepthUnaffected();
260 }
261 
262 // Tests that clearing depth/stencil followed by draw works when the depth/stencil attachment is a
263 // texture.
TEST_P(DepthStencilTestES3,ClearThenDraw)264 TEST_P(DepthStencilTestES3, ClearThenDraw)
265 {
266     GLFramebuffer FBO;
267     glBindFramebuffer(GL_FRAMEBUFFER, FBO);
268 
269     constexpr GLsizei kSize = 6;
270 
271     // Create framebuffer to draw into, with both color and depth attachments.
272     GLTexture color;
273     glBindTexture(GL_TEXTURE_2D, color);
274     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
275 
276     GLTexture depth;
277     glBindTexture(GL_TEXTURE_2D, depth);
278     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, kSize, kSize, 0, GL_DEPTH_STENCIL,
279                  GL_UNSIGNED_INT_24_8_OES, nullptr);
280 
281     GLFramebuffer fbo;
282     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
283     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
284     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
285     ASSERT_GL_NO_ERROR();
286 
287     // Set viewport and clear depth/stencil
288     glViewport(0, 0, kSize, kSize);
289     glClearDepthf(1);
290     glClearStencil(0x55);
291     glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
292 
293     // If depth is not cleared to 1, rendering would fail.
294     glEnable(GL_DEPTH_TEST);
295     glDepthFunc(GL_LESS);
296 
297     // If stencil is not clear to 0x55, rendering would fail.
298     glEnable(GL_STENCIL_TEST);
299     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
300     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
301     glStencilMask(0xFF);
302 
303     // Set up program
304     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
305 
306     // Draw red
307     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
308     ASSERT_GL_NO_ERROR();
309 
310     // Verify.
311     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
312     EXPECT_PIXEL_COLOR_EQ(kSize - 1, 0, GLColor::red);
313     EXPECT_PIXEL_COLOR_EQ(0, kSize - 1, GLColor::red);
314     EXPECT_PIXEL_COLOR_EQ(kSize - 1, kSize - 1, GLColor::red);
315 }
316 
compareDepth(uint32_t expected)317 void DepthStencilTestES3::compareDepth(uint32_t expected)
318 {
319     uint32_t pixel;
320     glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &pixel);
321     ASSERT_GL_NO_ERROR();
322 
323     // Right shift by 8 bits to only compare 24 depth bits
324     // and ignore 8 undefined bits.
325     pixel = pixel >> 8;
326 
327     EXPECT_NEAR(pixel, expected, 1);
328 }
329 
clearAndCompareDepth(GLfloat depth,uint32_t expected)330 void DepthStencilTestES3::clearAndCompareDepth(GLfloat depth, uint32_t expected)
331 {
332     glClearDepthf(depth);
333     glClear(GL_DEPTH_BUFFER_BIT);
334     compareDepth(expected);
335 }
336 
drawAndCompareDepth(GLProgram & program,GLfloat positionZ,uint32_t expected)337 void DepthStencilTestES3::drawAndCompareDepth(GLProgram &program,
338                                               GLfloat positionZ,
339                                               uint32_t expected)
340 {
341     glEnable(GL_DEPTH_TEST);
342     glDepthFunc(GL_ALWAYS);
343     drawQuad(program, essl3_shaders::PositionAttrib(), positionZ, 1.0f);
344     glDisable(GL_DEPTH_TEST);
345     compareDepth(expected);
346 }
347 
TEST_P(DepthStencilTestES3,ReadPixelsDepth24)348 TEST_P(DepthStencilTestES3, ReadPixelsDepth24)
349 {
350     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth24") ||
351                        !IsGLExtensionEnabled("GL_NV_read_depth"));
352 
353     // The test fails on native GLES on Android in glReadPixels
354     // with GL_INVALID_OPERATION due to the format/type combination
355     // not being supported.
356     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
357 
358     // Create GL_DEPTH_COMPONENT24 texture
359     GLTexture depthTexture;
360     glBindTexture(GL_TEXTURE_2D, depthTexture);
361     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, getWindowWidth(), getWindowHeight(), 0,
362                  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
363 
364     // Set up framebuffer
365     GLFramebuffer depthFBO;
366     GLRenderbuffer depthRenderbuffer;
367 
368     glBindFramebuffer(GL_FRAMEBUFFER, depthFBO);
369 
370     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
371     glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
372     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, getWindowWidth(),
373                           getWindowHeight());
374     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
375                               depthRenderbuffer);
376 
377     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
378     ASSERT_GL_NO_ERROR();
379 
380     // Test clear
381     clearAndCompareDepth(0.0f, 0x0);
382     clearAndCompareDepth(0.125f, 0x200000);
383     clearAndCompareDepth(0.5f, 0x800000);
384     clearAndCompareDepth(1.0f, 0xffffff);
385 
386     // Test draw
387     ANGLE_GL_PROGRAM(depthTestProgram, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
388     drawAndCompareDepth(depthTestProgram, 0.0f, 0x800000);
389     drawAndCompareDepth(depthTestProgram, 0.125f, 0x8fffff);
390     drawAndCompareDepth(depthTestProgram, 0.5f, 0xbfffff);
391     drawAndCompareDepth(depthTestProgram, 1.0f, 0xffffff);
392 
393     ASSERT_GL_NO_ERROR();
394 }
395 
396 // Tests that the stencil test is correctly handled when a framebuffer is cleared before that
397 // framebuffer's stencil attachment has been configured.
TEST_P(DepthStencilTestES3,FramebufferClearThenStencilAttachedThenStencilTestState)398 TEST_P(DepthStencilTestES3, FramebufferClearThenStencilAttachedThenStencilTestState)
399 {
400     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_read_stencil"));
401 
402     GLFramebuffer fbo;
403     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
404 
405     GLRenderbuffer colorRbo;
406     glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
407     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
408     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
409     glClearColor(0.f, 0.f, 0.f, 0.f);
410     glClear(GL_COLOR_BUFFER_BIT);
411 
412     GLRenderbuffer stencilRbo;
413     glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo);
414     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(), getWindowHeight());
415     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo);
416     glClearStencil(2);
417     glClear(GL_STENCIL_BUFFER_BIT);
418 
419     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
420     ASSERT_GL_NO_ERROR();
421 
422     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
423     EXPECT_PIXEL_STENCIL_EQ(0, 0, 2);
424 
425     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
426 
427     GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
428     ASSERT_NE(-1, colorLocation);
429 
430     glUseProgram(program);
431     glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
432 
433     glEnable(GL_STENCIL_TEST);
434     glStencilFunc(GL_ALWAYS, 0, 0xFF);
435     glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
436     drawQuad(program, "a_position", 0.5f);
437 
438     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
439     EXPECT_PIXEL_STENCIL_EQ(0, 0, 3);
440 }
441 
442 // Tests that the stencil test is correctly handled when both the stencil test state is configured
443 // and a framebuffer is cleared before that framebuffer's stencil attachment has been configured.
TEST_P(DepthStencilTestES3,StencilTestStateThenFramebufferClearThenStencilAttached)444 TEST_P(DepthStencilTestES3, StencilTestStateThenFramebufferClearThenStencilAttached)
445 {
446     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_read_stencil"));
447 
448     glEnable(GL_STENCIL_TEST);
449     glStencilFunc(GL_ALWAYS, 0, 0xFF);
450     glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
451 
452     GLFramebuffer fbo;
453     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
454 
455     GLRenderbuffer colorRbo;
456     glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
457     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
458     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
459     glClearColor(0.f, 0.f, 0.f, 0.f);
460     glClear(GL_COLOR_BUFFER_BIT);
461 
462     GLRenderbuffer stencilRbo;
463     glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo);
464     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(), getWindowHeight());
465     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo);
466     glClearStencil(2);
467     glClear(GL_STENCIL_BUFFER_BIT);
468 
469     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
470     ASSERT_GL_NO_ERROR();
471 
472     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
473     EXPECT_PIXEL_STENCIL_EQ(0, 0, 2);
474 
475     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
476 
477     GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
478     ASSERT_NE(-1, colorLocation);
479 
480     glUseProgram(program);
481     glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
482 
483     drawQuad(program, "a_position", 0.5f);
484 
485     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
486     EXPECT_PIXEL_STENCIL_EQ(0, 0, 3);
487 }
488 
489 // Tests that the stencil test is correctly handled when a framebuffer is cleared before that
490 // framebuffer's stencil attachment has been configured and the stencil test state is configured
491 // during framebuffer setup.
TEST_P(DepthStencilTestES3,FramebufferClearThenStencilTestStateThenStencilAttached)492 TEST_P(DepthStencilTestES3, FramebufferClearThenStencilTestStateThenStencilAttached)
493 {
494     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_read_stencil"));
495 
496     GLFramebuffer fbo;
497     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
498 
499     GLRenderbuffer colorRbo;
500     glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
501     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, getWindowWidth(), getWindowHeight());
502     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
503     glClearColor(0.f, 0.f, 0.f, 0.f);
504     glClear(GL_COLOR_BUFFER_BIT);
505 
506     glEnable(GL_STENCIL_TEST);
507     glStencilFunc(GL_ALWAYS, 0, 0xFF);
508     glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
509 
510     GLRenderbuffer stencilRbo;
511     glBindRenderbuffer(GL_RENDERBUFFER, stencilRbo);
512     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWindowWidth(), getWindowHeight());
513     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRbo);
514     glClearStencil(2);
515     glClear(GL_STENCIL_BUFFER_BIT);
516 
517     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
518     ASSERT_GL_NO_ERROR();
519 
520     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
521     EXPECT_PIXEL_STENCIL_EQ(0, 0, 2);
522 
523     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
524 
525     GLint colorLocation = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
526     ASSERT_NE(-1, colorLocation);
527 
528     glUseProgram(program);
529     glUniform4f(colorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
530 
531     drawQuad(program, "a_position", 0.5f);
532 
533     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
534     EXPECT_PIXEL_STENCIL_EQ(0, 0, 3);
535 }
536 
537 // Tests that drawing with read-only depth/stencil followed by depth/stencil output (in two render
538 // passes) works.  Regression test for a synchronization bug in the Vulkan backend, caught by
539 // syncval VVL.
TEST_P(DepthStencilTestES3,ReadOnlyDepthStencilThenOutputDepthStencil)540 TEST_P(DepthStencilTestES3, ReadOnlyDepthStencilThenOutputDepthStencil)
541 {
542     constexpr GLsizei kSize = 64;
543 
544     // Create FBO with color, depth and stencil
545     GLTexture texture;
546     glBindTexture(GL_TEXTURE_2D, texture);
547     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
548 
549     GLRenderbuffer renderbuffer;
550     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
551     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
552 
553     GLFramebuffer framebuffer;
554     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
555     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
556     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
557                               renderbuffer);
558     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
559     ASSERT_GL_NO_ERROR();
560 
561     // Initialize depth/stencil
562     glEnable(GL_DEPTH_TEST);
563     glDepthFunc(GL_ALWAYS);
564 
565     glEnable(GL_STENCIL_TEST);
566     glStencilFunc(GL_ALWAYS, 0xAA, 0xFF);
567     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
568     glStencilMask(0xFF);
569 
570     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
571     glUseProgram(drawColor);
572     GLint colorUniformLocation =
573         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
574     ASSERT_NE(colorUniformLocation, -1);
575 
576     // Draw red with depth = 1 and stencil = 0xAA
577     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
578     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 1);
579     ASSERT_GL_NO_ERROR();
580 
581     // Break the render pass by making a copy of the color texture.
582     GLTexture copyTex;
583     glBindTexture(GL_TEXTURE_2D, copyTex);
584     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
585     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, kSize / 2, kSize / 2);
586     ASSERT_GL_NO_ERROR();
587 
588     // Disable depth/stencil output and issue a draw call that's expected to pass depth/stencil.
589     glDepthFunc(GL_LESS);
590     glDepthMask(GL_FALSE);
591     glStencilFunc(GL_EQUAL, 0xAA, 0xFF);
592     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
593 
594     // Draw green
595     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
596     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95);
597     ASSERT_GL_NO_ERROR();
598 
599     // Break the render pass
600     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, 0, 0, 0, kSize / 2, kSize / 2);
601     ASSERT_GL_NO_ERROR();
602 
603     // Draw again to start another render pass still with depth/stencil read-only
604     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
605     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95);
606     ASSERT_GL_NO_ERROR();
607 
608     // Break the render pass
609     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, kSize / 2, 0, 0, kSize / 2, kSize / 2);
610     ASSERT_GL_NO_ERROR();
611 
612     // Re-enable depth/stencil output and issue a draw call that's expected to pass depth/stencil.
613     glDepthMask(GL_TRUE);
614     glStencilFunc(GL_EQUAL, 0xAB, 0xF0);
615     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
616 
617     // Draw yellow
618     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 0.0f, 1.0f);
619     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.95);
620     ASSERT_GL_NO_ERROR();
621 
622     // Break the render pass
623     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, kSize / 2, kSize / 2, 0, 0, kSize / 2, kSize / 2);
624     ASSERT_GL_NO_ERROR();
625 
626     GLFramebuffer readFramebuffer;
627     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
628     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyTex, 0);
629     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
630     EXPECT_PIXEL_COLOR_EQ(kSize / 2, 0, GLColor::green);
631     EXPECT_PIXEL_COLOR_EQ(0, kSize / 2, GLColor::blue);
632     EXPECT_PIXEL_COLOR_EQ(kSize / 2, kSize / 2, GLColor::yellow);
633 }
634 
635 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(DepthStencilTest);
636 
637 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DepthStencilTestES3);
638 ANGLE_INSTANTIATE_TEST_ES3(DepthStencilTestES3);
639 
640 }  // anonymous namespace
641