xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ClipControlTest.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 // Test cases for GL_EXT_clip_control
7 // These tests complement dEQP-GLES2.functional.clip_control.*
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 #include "util/EGLWindow.h"
13 #include "util/test_utils.h"
14 
15 using namespace angle;
16 
17 class ClipControlTest : public ANGLETest<>
18 {
19   protected:
20     static const int w = 64;
21     static const int h = 64;
22 
ClipControlTest()23     ClipControlTest()
24     {
25         setWindowWidth(w);
26         setWindowHeight(h);
27         setConfigRedBits(8);
28         setConfigGreenBits(8);
29         setConfigBlueBits(8);
30         setConfigAlphaBits(8);
31         setConfigDepthBits(24);
32         setExtensionsEnabled(false);
33     }
34 };
35 
36 // Test state queries and updates
TEST_P(ClipControlTest,StateQuery)37 TEST_P(ClipControlTest, StateQuery)
38 {
39     // Queries with the extension disabled
40     GLint clipOrigin = -1;
41     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
42     EXPECT_EQ(clipOrigin, -1);
43     EXPECT_GL_ERROR(GL_INVALID_ENUM);
44     GLint clipDepthMode = -1;
45     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
46     EXPECT_EQ(clipDepthMode, -1);
47     EXPECT_GL_ERROR(GL_INVALID_ENUM);
48 
49     // Command with the extension disabled
50     glClipControlEXT(GL_UPPER_LEFT_EXT, GL_ZERO_TO_ONE_EXT);
51     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
52 
53     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
54     ASSERT_GL_NO_ERROR();
55 
56     // Default state with the extension enabled
57     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
58     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
59     EXPECT_GLENUM_EQ(GL_LOWER_LEFT_EXT, clipOrigin);
60     EXPECT_GLENUM_EQ(GL_NEGATIVE_ONE_TO_ONE_EXT, clipDepthMode);
61 
62     ASSERT_GL_NO_ERROR();
63 
64     // Check valid state updates
65     glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
66     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
67     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
68     EXPECT_GLENUM_EQ(GL_LOWER_LEFT_EXT, clipOrigin);
69     EXPECT_GLENUM_EQ(GL_NEGATIVE_ONE_TO_ONE_EXT, clipDepthMode);
70 
71     glClipControlEXT(GL_LOWER_LEFT_EXT, GL_ZERO_TO_ONE_EXT);
72     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
73     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
74     EXPECT_GLENUM_EQ(GL_LOWER_LEFT_EXT, clipOrigin);
75     EXPECT_GLENUM_EQ(GL_ZERO_TO_ONE_EXT, clipDepthMode);
76 
77     glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
78     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
79     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
80     EXPECT_GLENUM_EQ(GL_UPPER_LEFT_EXT, clipOrigin);
81     EXPECT_GLENUM_EQ(GL_NEGATIVE_ONE_TO_ONE_EXT, clipDepthMode);
82 
83     glClipControlEXT(GL_UPPER_LEFT_EXT, GL_ZERO_TO_ONE_EXT);
84     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
85     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
86     EXPECT_GLENUM_EQ(GL_UPPER_LEFT_EXT, clipOrigin);
87     EXPECT_GLENUM_EQ(GL_ZERO_TO_ONE_EXT, clipDepthMode);
88 
89     ASSERT_GL_NO_ERROR();
90 
91     // Check invalid state updates
92     glClipControlEXT(GL_LOWER_LEFT_EXT, 0);
93     EXPECT_GL_ERROR(GL_INVALID_ENUM);
94     glClipControlEXT(0, GL_NEGATIVE_ONE_TO_ONE_EXT);
95     EXPECT_GL_ERROR(GL_INVALID_ENUM);
96 
97     // Invalid command does not change the state
98     glGetIntegerv(GL_CLIP_ORIGIN_EXT, &clipOrigin);
99     glGetIntegerv(GL_CLIP_DEPTH_MODE_EXT, &clipDepthMode);
100     EXPECT_GLENUM_EQ(GL_UPPER_LEFT_EXT, clipOrigin);
101     EXPECT_GLENUM_EQ(GL_ZERO_TO_ONE_EXT, clipDepthMode);
102 
103     ASSERT_GL_NO_ERROR();
104 }
105 
106 // Test that clip origin does not affect scissored clears
TEST_P(ClipControlTest,OriginScissorClear)107 TEST_P(ClipControlTest, OriginScissorClear)
108 {
109     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
110 
111     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
112 
113     auto test = [&](std::string name, bool useES3) {
114         // Start with lower-left
115         glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
116 
117         // Make a draw call without color writes to sync the state
118         glColorMask(false, false, false, false);
119         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
120         glColorMask(true, true, true, true);
121 
122         // Clear to red
123         glDisable(GL_SCISSOR_TEST);
124         if (useES3)
125         {
126             float color[4] = {1.0, 0.0, 0.0, 1.0};
127             glClearBufferfv(GL_COLOR, 0, color);
128         }
129         else
130         {
131             glClearColor(1.0, 0.0, 0.0, 1.0);
132             glClear(GL_COLOR_BUFFER_BIT);
133         }
134 
135         // Flip the clip origin
136         glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
137 
138         // Make a draw call without color writes to sync the state
139         glColorMask(false, false, false, false);
140         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
141         glColorMask(true, true, true, true);
142 
143         // Clear lower half to green
144         glEnable(GL_SCISSOR_TEST);
145         glScissor(0, 0, w, h / 2);
146         if (useES3)
147         {
148             float color[4] = {0.0, 1.0, 0.0, 1.0};
149             glClearBufferfv(GL_COLOR, 0, color);
150         }
151         else
152         {
153             glClearColor(0.0, 1.0, 0.0, 1.0);
154             glClear(GL_COLOR_BUFFER_BIT);
155         }
156         ASSERT_GL_NO_ERROR();
157 
158         EXPECT_PIXEL_COLOR_EQ(0.5 * w, 0.25 * h, GLColor::green) << name;
159         EXPECT_PIXEL_COLOR_EQ(0.5 * w, 0.75 * h, GLColor::red) << name;
160     };
161 
162     test("Default framebuffer", getClientMajorVersion() > 2);
163 
164     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_rgb8_rgba8"));
165 
166     GLRenderbuffer rb;
167     glBindRenderbuffer(GL_RENDERBUFFER, rb);
168     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h);
169 
170     GLFramebuffer fb;
171     glBindFramebuffer(GL_FRAMEBUFFER, fb);
172     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
173     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
174 
175     test("User framebuffer", getClientMajorVersion() > 2);
176 }
177 
178 // Test that changing clip origin state does not affect location of scissor area
TEST_P(ClipControlTest,OriginScissorDraw)179 TEST_P(ClipControlTest, OriginScissorDraw)
180 {
181     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
182 
183     constexpr char kVS[] = R"(
184 attribute vec2 a_position;
185 void main()
186 {
187     // Square at (0.25, 0.25) -> (0.75, 0.75)
188     gl_Position = vec4(a_position * 0.25 + 0.5, 0.0, 1.0);
189 })";
190 
191     ANGLE_GL_PROGRAM(program, kVS, essl1_shaders::fs::Blue());
192     glUseProgram(program);
193     ASSERT_GL_NO_ERROR();
194 
195     auto test = [&](std::string name) {
196         glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
197 
198         glDisable(GL_SCISSOR_TEST);
199         glClear(GL_COLOR_BUFFER_BIT);
200 
201         // Draw only to the lower half
202         glEnable(GL_SCISSOR_TEST);
203         glScissor(0, 0, w, h / 2);
204 
205         // Draw blue quad in the upper-right part of the framebuffer; scissor test must fail
206         drawQuad(program, "a_position", 0);
207         ASSERT_GL_NO_ERROR();
208 
209         // Switch the clip origin and draw again; scissor test must pass
210         glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
211         drawQuad(program, "a_position", 0);
212         ASSERT_GL_NO_ERROR();
213 
214         // Reads are unaffected by clip origin
215         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.25 * h, GLColor::blue) << name;
216         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.75 * h, GLColor::transparentBlack) << name;
217     };
218 
219     test("Default framebuffer");
220 
221     GLFramebuffer fb;
222     glBindFramebuffer(GL_FRAMEBUFFER, fb);
223 
224     GLRenderbuffer rb;
225     glBindRenderbuffer(GL_RENDERBUFFER, rb);
226     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, w, h);
227     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
228     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
229 
230     test("User framebuffer");
231 }
232 
233 // Test that changing clip origin state does not affect copyTexImage
TEST_P(ClipControlTest,OriginCopyTexImage)234 TEST_P(ClipControlTest, OriginCopyTexImage)
235 {
236     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
237 
238     auto test = [&](std::string name) {
239         glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
240 
241         // Clear to red
242         glDisable(GL_SCISSOR_TEST);
243         glClearColor(1.0, 0.0, 0.0, 1.0);
244         glClear(GL_COLOR_BUFFER_BIT);
245 
246         // Clear lower half-space to green
247         glEnable(GL_SCISSOR_TEST);
248         glScissor(0, 0, w, h / 2);
249         glClearColor(0.0, 1.0, 0.0, 1.0);
250         glClear(GL_COLOR_BUFFER_BIT);
251 
252         // Switch clip origin state, it must have no effect on the next commands
253         glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
254 
255         GLTexture tex;
256         glBindTexture(GL_TEXTURE_2D, tex);
257         glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, w / 4, h / 4, 0);
258         ASSERT_GL_NO_ERROR();
259 
260         GLFramebuffer readFb;
261         glBindFramebuffer(GL_FRAMEBUFFER, readFb);
262         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
263         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
264 
265         // Copied texture must contain values from the lower half-space
266         EXPECT_PIXEL_COLOR_EQ(w / 8, h / 8, GLColor::green) << name;
267     };
268 
269     test("Default framebuffer");
270 
271     GLFramebuffer fb;
272     glBindFramebuffer(GL_FRAMEBUFFER, fb);
273 
274     GLRenderbuffer rb;
275     glBindRenderbuffer(GL_RENDERBUFFER, rb);
276     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, w, h);
277     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
278     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
279 
280     test("User framebuffer");
281 }
282 
283 // Test that changing clip origin state does not affect copyTexImage
284 // with Luma format that may use draw calls internally
TEST_P(ClipControlTest,OriginCopyTexImageLuma)285 TEST_P(ClipControlTest, OriginCopyTexImageLuma)
286 {
287     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
288 
289     glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
290 
291     // Clear to zero
292     glClear(GL_COLOR_BUFFER_BIT);
293 
294     // Clear lower half-space to one
295     glEnable(GL_SCISSOR_TEST);
296     glScissor(0, 0, w, h / 2);
297     glClearColor(1.0, 1.0, 1.0, 1.0);
298     glClear(GL_COLOR_BUFFER_BIT);
299     glDisable(GL_SCISSOR_TEST);
300 
301     // Switch clip origin state, it must have no effect on the next commands
302     glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
303 
304     GLTexture tex;
305     glBindTexture(GL_TEXTURE_2D, tex);
306     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
307     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
308     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, w, h, 0);
309     ASSERT_GL_NO_ERROR();
310 
311     glClearColor(1.0, 0.0, 1.0, 1.0);
312     glClear(GL_COLOR_BUFFER_BIT);
313     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
314 
315     // Draw the luma texture
316     glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
317     ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
318     drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.0f);
319     ASSERT_GL_NO_ERROR();
320 
321     EXPECT_PIXEL_COLOR_EQ(w / 2, h * 1 / 4, GLColor::white);
322     EXPECT_PIXEL_COLOR_EQ(w / 2, h * 3 / 4, GLColor::black);
323 }
324 
325 // Test that clip origin does not affect gl_FragCoord
TEST_P(ClipControlTest,OriginFragCoord)326 TEST_P(ClipControlTest, OriginFragCoord)
327 {
328     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
329 
330     const char kFS[] = R"(precision mediump float;
331 void main()
332 {
333     gl_FragColor = vec4(sign(gl_FragCoord.xy / 64.0 - 0.5), 0.0, 1.0);
334 })";
335 
336     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
337 
338     glClearColor(1.0, 0.0, 1.0, 1.0);
339 
340     for (GLenum origin : {GL_LOWER_LEFT_EXT, GL_UPPER_LEFT_EXT})
341     {
342         glClipControlEXT(origin, GL_NEGATIVE_ONE_TO_ONE_EXT);
343 
344         glBindFramebuffer(GL_FRAMEBUFFER, 0);
345 
346         glClear(GL_COLOR_BUFFER_BIT);
347         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
348 
349         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
350         EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::red);
351         EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::green);
352         EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::yellow);
353 
354         GLFramebuffer fb;
355         glBindFramebuffer(GL_FRAMEBUFFER, fb);
356 
357         GLRenderbuffer rb;
358         glBindRenderbuffer(GL_RENDERBUFFER, rb);
359         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, w, h);
360         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
361         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
362 
363         glClear(GL_COLOR_BUFFER_BIT);
364         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
365 
366         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
367         EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::red);
368         EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::green);
369         EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::yellow);
370     }
371 }
372 
373 // Test that clip origin does not affect gl_PointCoord
TEST_P(ClipControlTest,OriginPointCoord)374 TEST_P(ClipControlTest, OriginPointCoord)
375 {
376     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
377 
378     float pointSizeRange[2] = {};
379     glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
380     ANGLE_SKIP_TEST_IF(pointSizeRange[1] < 32);
381 
382     const char kVS[] = R"(precision mediump float;
383 void main()
384 {
385     gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
386     gl_PointSize = 32.0;
387 })";
388 
389     const char kFS[] = R"(precision mediump float;
390 void main()
391 {
392     gl_FragColor = vec4(sign(gl_PointCoord.xy - 0.5), 0.0, 1.0);
393 })";
394 
395     ANGLE_GL_PROGRAM(program, kVS, kFS);
396     glUseProgram(program);
397     ASSERT_GL_NO_ERROR();
398 
399     glClearColor(1.0, 0.0, 1.0, 1.0);
400 
401     for (GLenum origin : {GL_LOWER_LEFT_EXT, GL_UPPER_LEFT_EXT})
402     {
403         glClipControlEXT(origin, GL_NEGATIVE_ONE_TO_ONE_EXT);
404 
405         glBindFramebuffer(GL_FRAMEBUFFER, 0);
406 
407         glClear(GL_COLOR_BUFFER_BIT);
408         glDrawArrays(GL_POINTS, 0, 1);
409         ASSERT_GL_NO_ERROR();
410 
411         EXPECT_PIXEL_COLOR_EQ(w / 2 - 15, h / 2 + 15, GLColor::black);
412         EXPECT_PIXEL_COLOR_EQ(w / 2 + 15, h / 2 + 15, GLColor::red);
413         EXPECT_PIXEL_COLOR_EQ(w / 2 - 15, h / 2 - 15, GLColor::green);
414         EXPECT_PIXEL_COLOR_EQ(w / 2 + 15, h / 2 - 15, GLColor::yellow);
415 
416         GLFramebuffer fb;
417         glBindFramebuffer(GL_FRAMEBUFFER, fb);
418 
419         GLRenderbuffer rb;
420         glBindRenderbuffer(GL_RENDERBUFFER, rb);
421         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, w, h);
422         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
423         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
424 
425         glClear(GL_COLOR_BUFFER_BIT);
426         glDrawArrays(GL_POINTS, 0, 1);
427         ASSERT_GL_NO_ERROR();
428 
429         EXPECT_PIXEL_COLOR_EQ(w / 2 - 15, h / 2 + 15, GLColor::black);
430         EXPECT_PIXEL_COLOR_EQ(w / 2 + 15, h / 2 + 15, GLColor::red);
431         EXPECT_PIXEL_COLOR_EQ(w / 2 - 15, h / 2 - 15, GLColor::green);
432         EXPECT_PIXEL_COLOR_EQ(w / 2 + 15, h / 2 - 15, GLColor::yellow);
433     }
434 }
435 
436 // Test that clip origin does not affect gl_FrontFacing
TEST_P(ClipControlTest,OriginFrontFacing)437 TEST_P(ClipControlTest, OriginFrontFacing)
438 {
439     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
440 
441     const char kFS[] = R"(precision mediump float;
442 void main()
443 {
444     gl_FragColor = vec4(gl_FrontFacing ? vec2(1.0, 0.0) : vec2(0.0, 1.0), 0.0, 1.0);
445 })";
446 
447     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
448 
449     for (GLenum origin : {GL_LOWER_LEFT_EXT, GL_UPPER_LEFT_EXT})
450     {
451         glClipControlEXT(origin, GL_NEGATIVE_ONE_TO_ONE_EXT);
452 
453         glBindFramebuffer(GL_FRAMEBUFFER, 0);
454 
455         glFrontFace(GL_CCW);
456         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
457         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
458 
459         glFrontFace(GL_CW);
460         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
461         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
462 
463         GLFramebuffer fb;
464         glBindFramebuffer(GL_FRAMEBUFFER, fb);
465 
466         GLRenderbuffer rb;
467         glBindRenderbuffer(GL_RENDERBUFFER, rb);
468         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, w, h);
469         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
470         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
471 
472         glFrontFace(GL_CCW);
473         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
474         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
475 
476         glFrontFace(GL_CW);
477         drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
478         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
479     }
480 }
481 
482 // Test that clip origin does not affect readPixels
TEST_P(ClipControlTest,OriginReadPixels)483 TEST_P(ClipControlTest, OriginReadPixels)
484 {
485     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
486 
487     const char kFS[] = R"(precision mediump float;
488 uniform float blue;
489 varying vec4 v_position;
490 void main()
491 {
492     gl_FragColor = (v_position.y > 0.0) ? vec4(1.0, 0.0, blue, 1.0) : vec4(0.0, 1.0, blue, 1.0);
493 })";
494 
495     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), kFS);
496     const GLint blueUniformLocation = glGetUniformLocation(program, "blue");
497     glUseProgram(program);
498 
499     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
500 
501     glEnable(GL_DEPTH_TEST);
502 
503     glUniform1f(blueUniformLocation, 0.0f);
504     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
505     EXPECT_PIXEL_RECT_EQ(0, h / 2 + 2, w, h / 2 - 2, GLColor::red);
506     EXPECT_PIXEL_RECT_EQ(0, 0, w, h / 2 - 2, GLColor::green);
507 
508     // Update clip origin and make a draw call that fails the depth test to
509     // ensure that the backend is synced while the framebuffer is unchanged.
510     glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
511     glUniform1f(blueUniformLocation, 1.0f);
512     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0);
513 
514     // Check that the second draw call has failed the depth test and
515     // reading from the framebuffer returns the same values as before.
516     EXPECT_PIXEL_RECT_EQ(0, h / 2 + 2, w, h / 2 - 2, GLColor::red);
517     EXPECT_PIXEL_RECT_EQ(0, 0, w, h / 2 - 2, GLColor::green);
518 }
519 
520 // Test that changing only the clip depth mode syncs the state correctly
TEST_P(ClipControlTest,DepthModeSimple)521 TEST_P(ClipControlTest, DepthModeSimple)
522 {
523     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
524 
525     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
526     const GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
527     glUseProgram(program);
528     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
529 
530     glEnable(GL_DEPTH_TEST);
531 
532     glUniform4fv(colorUniformLocation, 1, GLColor::red.toNormalizedVector().data());
533     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
534 
535     glClipControlEXT(GL_LOWER_LEFT_EXT, GL_ZERO_TO_ONE_EXT);
536 
537     glUniform4fv(colorUniformLocation, 1, GLColor::green.toNormalizedVector().data());
538     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
539 
540     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
541 }
542 
543 // Test that gl_FragCoord.z has expected values for ZERO_TO_ONE clip depth mode
TEST_P(ClipControlTest,DepthFragCoord)544 TEST_P(ClipControlTest, DepthFragCoord)
545 {
546     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
547 
548     const char kFS[] = R"(precision mediump float;
549 void main()
550 {
551     gl_FragColor = vec4(gl_FragCoord.z, 0, 0, 1);
552 })";
553     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
554 
555     glClipControlEXT(GL_LOWER_LEFT_EXT, GL_ZERO_TO_ONE_EXT);
556     ASSERT_GL_NO_ERROR();
557 
558     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0);
559     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
560 
561     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
562     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(127, 0, 0, 255), 1);
563 
564     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
565     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
566 }
567 
568 class ClipControlTestES3 : public ClipControlTest
569 {};
570 
571 // Test that clip origin state does not affect framebuffer blits
TEST_P(ClipControlTestES3,OriginBlit)572 TEST_P(ClipControlTestES3, OriginBlit)
573 {
574     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_clip_control"));
575 
576     constexpr char kFS[] = R"(
577 precision mediump float;
578 varying vec4 v_position;
579 void main()
580 {
581     gl_FragColor = vec4(sign(v_position.xy), 0.0, 1.0);
582 })";
583 
584     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), kFS);
585     glUseProgram(program);
586     ASSERT_GL_NO_ERROR();
587 
588     // Blit default to custom
589     {
590         GLFramebuffer fb;
591         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
592 
593         GLRenderbuffer rb;
594         glBindRenderbuffer(GL_RENDERBUFFER, rb);
595         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h);
596         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
597         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
598 
599         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
600         glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
601         drawQuad(program, "a_position", 0);
602         ASSERT_GL_NO_ERROR();
603 
604         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
605         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
606         glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
607         glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
608         ASSERT_GL_NO_ERROR();
609 
610         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
611         EXPECT_PIXEL_COLOR_EQ(0.25 * w, 0.25 * h, GLColor::black);
612         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.25 * h, GLColor::red);
613         EXPECT_PIXEL_COLOR_EQ(0.25 * w, 0.75 * h, GLColor::green);
614         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.75 * h, GLColor::yellow);
615     }
616 
617     // Blit custom to default
618     {
619         GLFramebuffer fb;
620         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
621 
622         GLRenderbuffer rb;
623         glBindRenderbuffer(GL_RENDERBUFFER, rb);
624         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h);
625         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
626         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
627 
628         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb);
629         glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
630         drawQuad(program, "a_position", 0);
631         ASSERT_GL_NO_ERROR();
632 
633         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
634         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
635         glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
636         glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
637         ASSERT_GL_NO_ERROR();
638 
639         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
640         EXPECT_PIXEL_COLOR_EQ(0.25 * w, 0.25 * h, GLColor::black);
641         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.25 * h, GLColor::red);
642         EXPECT_PIXEL_COLOR_EQ(0.25 * w, 0.75 * h, GLColor::green);
643         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.75 * h, GLColor::yellow);
644     }
645 
646     // Blit custom to custom
647     {
648         GLFramebuffer fb1;
649         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb1);
650 
651         GLRenderbuffer rb1;
652         glBindRenderbuffer(GL_RENDERBUFFER, rb1);
653         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h);
654         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb1);
655         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
656 
657         GLFramebuffer fb2;
658         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb2);
659 
660         GLRenderbuffer rb2;
661         glBindRenderbuffer(GL_RENDERBUFFER, rb2);
662         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, w, h);
663         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb2);
664         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
665 
666         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb1);
667         glClipControlEXT(GL_LOWER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
668         drawQuad(program, "a_position", 0);
669         ASSERT_GL_NO_ERROR();
670 
671         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb1);
672         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb2);
673         glClipControlEXT(GL_UPPER_LEFT_EXT, GL_NEGATIVE_ONE_TO_ONE_EXT);
674         glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
675         ASSERT_GL_NO_ERROR();
676 
677         glBindFramebuffer(GL_READ_FRAMEBUFFER, fb2);
678         EXPECT_PIXEL_COLOR_EQ(0.25 * w, 0.25 * h, GLColor::black);
679         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.25 * h, GLColor::red);
680         EXPECT_PIXEL_COLOR_EQ(0.25 * w, 0.75 * h, GLColor::green);
681         EXPECT_PIXEL_COLOR_EQ(0.75 * w, 0.75 * h, GLColor::yellow);
682     }
683 }
684 
685 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(ClipControlTest,
686                                        ES2_OPENGLES().enable(Feature::EmulateClipOrigin),
687                                        ES3_OPENGLES().enable(Feature::EmulateClipOrigin));
688 ANGLE_INSTANTIATE_TEST_ES3_AND(ClipControlTestES3,
689                                ES3_OPENGLES().enable(Feature::EmulateClipOrigin));
690