xref: /aosp_15_r20/external/angle/src/tests/gl_tests/PolygonModeTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2023 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 // PolygonModeTest.cpp: Test cases for GL_NV_polygon_mode and GL_ANGLE_polygon_mode
7 //
8 
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 
12 using namespace angle;
13 
14 class PolygonModeTest : public ANGLETest<>
15 {
16   protected:
PolygonModeTest()17     PolygonModeTest()
18     {
19         setConfigRedBits(8);
20         setConfigGreenBits(8);
21         setConfigBlueBits(8);
22         setConfigAlphaBits(8);
23         setConfigDepthBits(24);
24         setExtensionsEnabled(false);
25         setWindowWidth(16);
26         setWindowHeight(16);
27     }
28 };
29 
30 // New state queries and commands fail without the extension
TEST_P(PolygonModeTest,NoExtension)31 TEST_P(PolygonModeTest, NoExtension)
32 {
33     {
34         GLint mode = 0;
35         glGetIntegerv(GL_POLYGON_MODE_NV, &mode);
36         EXPECT_GL_ERROR(GL_INVALID_ENUM);
37         EXPECT_EQ(mode, 0);
38 
39         glPolygonModeNV(GL_FRONT_AND_BACK, GL_FILL_NV);
40         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
41 
42         glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_FILL_NV);
43         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
44     }
45     for (GLenum state : {GL_POLYGON_OFFSET_POINT_NV, GL_POLYGON_OFFSET_LINE_NV})
46     {
47         EXPECT_FALSE(glIsEnabled(state));
48         EXPECT_GL_ERROR(GL_INVALID_ENUM);
49 
50         GLboolean enabled = true;
51         glGetBooleanv(state, &enabled);
52         EXPECT_GL_ERROR(GL_INVALID_ENUM);
53         EXPECT_TRUE(enabled);
54 
55         glEnable(state);
56         EXPECT_GL_ERROR(GL_INVALID_ENUM);
57 
58         glDisable(state);
59         EXPECT_GL_ERROR(GL_INVALID_ENUM);
60     }
61 }
62 
63 // Test NV_polygon_mode entrypoints
TEST_P(PolygonModeTest,ExtensionStateNV)64 TEST_P(PolygonModeTest, ExtensionStateNV)
65 {
66     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_NV_polygon_mode"));
67 
68     // Default state
69     {
70         GLint mode = 0;
71         glGetIntegerv(GL_POLYGON_MODE_NV, &mode);
72         EXPECT_GLENUM_EQ(GL_FILL_NV, mode);
73         EXPECT_GL_NO_ERROR();
74     }
75     for (GLenum state : {GL_POLYGON_OFFSET_POINT_NV, GL_POLYGON_OFFSET_LINE_NV})
76     {
77         EXPECT_FALSE(glIsEnabled(state));
78         EXPECT_GL_NO_ERROR();
79 
80         GLboolean enabled = true;
81         glGetBooleanv(state, &enabled);
82         EXPECT_FALSE(enabled);
83         EXPECT_GL_NO_ERROR();
84     }
85 
86     // Polygon mode state updates
87     for (GLenum mode : {GL_POINT_NV, GL_LINE_NV, GL_FILL_NV})
88     {
89         glPolygonModeNV(GL_FRONT_AND_BACK, mode);
90         EXPECT_GL_NO_ERROR();
91 
92         GLint result = 0;
93         glGetIntegerv(GL_POLYGON_MODE_NV, &result);
94         EXPECT_GLENUM_EQ(mode, result);
95         EXPECT_GL_NO_ERROR();
96     }
97 
98     // Polygon offset state updates
99     for (GLenum state : {GL_POLYGON_OFFSET_POINT_NV, GL_POLYGON_OFFSET_LINE_NV})
100     {
101         GLboolean enabled = false;
102 
103         glEnable(state);
104         EXPECT_GL_NO_ERROR();
105 
106         EXPECT_TRUE(glIsEnabled(state));
107         EXPECT_GL_NO_ERROR();
108 
109         glGetBooleanv(state, &enabled);
110         EXPECT_GL_NO_ERROR();
111         EXPECT_TRUE(enabled);
112 
113         glDisable(state);
114         EXPECT_GL_NO_ERROR();
115 
116         EXPECT_FALSE(glIsEnabled(state));
117         EXPECT_GL_NO_ERROR();
118 
119         glGetBooleanv(state, &enabled);
120         EXPECT_GL_NO_ERROR();
121         EXPECT_FALSE(enabled);
122     }
123 
124     // Errors
125     {
126         glPolygonModeNV(GL_FRONT, GL_FILL_NV);
127         EXPECT_GL_ERROR(GL_INVALID_ENUM);
128 
129         glPolygonModeNV(GL_BACK, GL_FILL_NV);
130         EXPECT_GL_ERROR(GL_INVALID_ENUM);
131 
132         glPolygonModeNV(GL_FRONT_AND_BACK, 0);
133         EXPECT_GL_ERROR(GL_INVALID_ENUM);
134     }
135 }
136 
137 // Test ANGLE_polygon_mode entrypoints
TEST_P(PolygonModeTest,ExtensionStateANGLE)138 TEST_P(PolygonModeTest, ExtensionStateANGLE)
139 {
140     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_polygon_mode"));
141 
142     // Default state
143     {
144         GLint mode = 0;
145         glGetIntegerv(GL_POLYGON_MODE_ANGLE, &mode);
146         EXPECT_GLENUM_EQ(GL_FILL_ANGLE, mode);
147         EXPECT_GL_NO_ERROR();
148     }
149     for (GLenum state : {GL_POLYGON_OFFSET_LINE_ANGLE})
150     {
151         EXPECT_FALSE(glIsEnabled(state));
152         EXPECT_GL_NO_ERROR();
153 
154         GLboolean enabled = true;
155         glGetBooleanv(state, &enabled);
156         EXPECT_FALSE(enabled);
157         EXPECT_GL_NO_ERROR();
158     }
159 
160     // Polygon mode state updates
161     for (GLenum mode : {GL_LINE_ANGLE, GL_FILL_ANGLE})
162     {
163         glPolygonModeANGLE(GL_FRONT_AND_BACK, mode);
164         EXPECT_GL_NO_ERROR();
165 
166         GLint result = 0;
167         glGetIntegerv(GL_POLYGON_MODE_ANGLE, &result);
168         EXPECT_GLENUM_EQ(mode, result);
169         EXPECT_GL_NO_ERROR();
170     }
171 
172     // Polygon offset state updates
173     for (GLenum state : {GL_POLYGON_OFFSET_LINE_ANGLE})
174     {
175         GLboolean enabled = false;
176 
177         glEnable(state);
178         EXPECT_GL_NO_ERROR();
179 
180         EXPECT_TRUE(glIsEnabled(state));
181         EXPECT_GL_NO_ERROR();
182 
183         glGetBooleanv(state, &enabled);
184         EXPECT_GL_NO_ERROR();
185         EXPECT_TRUE(enabled);
186 
187         glDisable(state);
188         EXPECT_GL_NO_ERROR();
189 
190         EXPECT_FALSE(glIsEnabled(state));
191         EXPECT_GL_NO_ERROR();
192 
193         glGetBooleanv(state, &enabled);
194         EXPECT_GL_NO_ERROR();
195         EXPECT_FALSE(enabled);
196     }
197 
198     // Errors
199     {
200         glPolygonModeANGLE(GL_FRONT, GL_FILL_ANGLE);
201         EXPECT_GL_ERROR(GL_INVALID_ENUM);
202 
203         glPolygonModeANGLE(GL_BACK, GL_FILL_ANGLE);
204         EXPECT_GL_ERROR(GL_INVALID_ENUM);
205 
206         glPolygonModeANGLE(GL_FRONT_AND_BACK, 0);
207         EXPECT_GL_ERROR(GL_INVALID_ENUM);
208 
209         glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_POINT_NV);
210         EXPECT_GL_ERROR(GL_INVALID_ENUM);
211 
212         glIsEnabled(GL_POLYGON_OFFSET_POINT_NV);
213         EXPECT_GL_ERROR(GL_INVALID_ENUM);
214 
215         GLboolean enabled = true;
216         glGetBooleanv(GL_POLYGON_OFFSET_POINT_NV, &enabled);
217         EXPECT_GL_ERROR(GL_INVALID_ENUM);
218     }
219 }
220 
221 // Test line rasterization mode
TEST_P(PolygonModeTest,DrawLines)222 TEST_P(PolygonModeTest, DrawLines)
223 {
224     const bool extensionNV    = EnsureGLExtensionEnabled("GL_NV_polygon_mode");
225     const bool extensionANGLE = EnsureGLExtensionEnabled("GL_ANGLE_polygon_mode");
226     ANGLE_SKIP_TEST_IF(!extensionNV && !extensionANGLE);
227 
228     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
229     glUseProgram(program);
230     GLint colorLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
231 
232     const int w = getWindowWidth();
233     const int h = getWindowHeight();
234     ASSERT(w == h);
235 
236     for (bool useNV : {true, false})
237     {
238         if (useNV && !extensionNV)
239         {
240             continue;
241         }
242 
243         glClearColor(1, 0, 0, 1);
244         glClear(GL_COLOR_BUFFER_BIT);
245         EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
246 
247         // Draw green quad with lines
248         if (useNV)
249         {
250             glPolygonModeNV(GL_FRONT_AND_BACK, GL_LINE_NV);
251         }
252         else
253         {
254             glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_LINE_ANGLE);
255         }
256         glUniform4f(colorLocation, 0.0, 1.0, 0.0, 1.0);
257         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
258 
259         // Nothing was drawn inside triangles
260         EXPECT_PIXEL_RECT_EQ(1, 1, 5, 5, GLColor::red);
261         EXPECT_PIXEL_RECT_EQ(9, 9, 5, 5, GLColor::red);
262 
263         // Main diagonal was drawn
264         std::vector<GLColor> colors(w * h);
265         glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
266         for (int i = 0; i < w; i++)
267         {
268             const int x = i;
269             const int y = w - 1 - i;
270             EXPECT_EQ(GLColor::green, colors[y * w + x]) << "x: " << x << " y: " << y;
271         }
272 
273         // Draw blue quad with triangles
274         if (useNV)
275         {
276             glPolygonModeNV(GL_FRONT_AND_BACK, GL_FILL_NV);
277         }
278         else
279         {
280             glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_FILL_ANGLE);
281         }
282         glUniform4f(colorLocation, 0.0, 0.0, 1.0, 1.0);
283         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
284         EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue);
285     }
286 }
287 
288 // Test line rasterization mode with depth offset
TEST_P(PolygonModeTest,DrawLinesWithDepthOffset)289 TEST_P(PolygonModeTest, DrawLinesWithDepthOffset)
290 {
291     const bool extensionNV    = EnsureGLExtensionEnabled("GL_NV_polygon_mode");
292     const bool extensionANGLE = EnsureGLExtensionEnabled("GL_ANGLE_polygon_mode");
293     ANGLE_SKIP_TEST_IF(!extensionNV && !extensionANGLE);
294 
295     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
296     glUseProgram(program);
297     GLint colorLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
298 
299     const int w = getWindowWidth();
300     const int h = getWindowHeight();
301     ASSERT(w == h);
302 
303     glEnable(GL_DEPTH_TEST);
304 
305     for (bool useNV : {true, false})
306     {
307         if (useNV && !extensionNV)
308         {
309             continue;
310         }
311 
312         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
313 
314         // Draw red quad filled
315         if (useNV)
316         {
317             glPolygonModeNV(GL_FRONT_AND_BACK, GL_FILL_NV);
318         }
319         else
320         {
321             glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_FILL_ANGLE);
322         }
323         glUniform4f(colorLocation, 1.0, 0.0, 0.0, 1.0);
324         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
325 
326         // Draw green quad using lines with offset failing the depth test
327         if (useNV)
328         {
329             glEnable(GL_POLYGON_OFFSET_LINE_NV);
330             glPolygonModeNV(GL_FRONT_AND_BACK, GL_LINE_NV);
331         }
332         else
333         {
334             glEnable(GL_POLYGON_OFFSET_LINE_ANGLE);
335             glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_LINE_ANGLE);
336         }
337         glPolygonOffset(0.0, 2.0);
338         glUniform4f(colorLocation, 0.0, 1.0, 0.0, 1.0);
339         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
340 
341         // Depth test must fail
342         EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
343 
344         // Draw green quad with triangles
345         if (useNV)
346         {
347             glPolygonModeNV(GL_FRONT_AND_BACK, GL_FILL_NV);
348         }
349         else
350         {
351             glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_FILL_ANGLE);
352         }
353         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
354 
355         // Change the offset so that depth test passes
356         glPolygonOffset(0.0, -2.0);
357 
358         // Draw blue quad with lines
359         if (useNV)
360         {
361             glPolygonModeNV(GL_FRONT_AND_BACK, GL_LINE_NV);
362         }
363         else
364         {
365             glPolygonModeANGLE(GL_FRONT_AND_BACK, GL_LINE_ANGLE);
366         }
367         glUniform4f(colorLocation, 0.0, 0.0, 1.0, 1.0);
368         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
369 
370         // Main diagonal was drawn
371         std::vector<GLColor> colors(w * h);
372         glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
373         for (int i = 0; i < w; i++)
374         {
375             const int x = i;
376             const int y = w - 1 - i;
377             EXPECT_EQ(GLColor::blue, colors[y * w + x]) << "x: " << x << " y: " << y;
378         }
379     }
380 }
381 
382 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PolygonModeTest);
383