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