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