• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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 // ClipDistanceTest.cpp: Test cases for GL_APPLE_clip_distance/GL_EXT_clip_cull_distance extension.
7 //
8 
9 #include "test_utils/ANGLETest.h"
10 #include "test_utils/gl_raii.h"
11 #include "util/EGLWindow.h"
12 #include "util/test_utils.h"
13 
14 using namespace angle;
15 
16 class ClipDistanceTest : public ANGLETest
17 {
18   protected:
ClipDistanceTest()19     ClipDistanceTest()
20     {
21         setWindowWidth(16);
22         setWindowHeight(16);
23         setConfigRedBits(8);
24         setConfigGreenBits(8);
25         setConfigBlueBits(8);
26         setConfigAlphaBits(8);
27         setConfigDepthBits(24);
28     }
29 };
30 
31 // Query max clip distances and enable, disable states of clip distances
TEST_P(ClipDistanceTest,StateQuery)32 TEST_P(ClipDistanceTest, StateQuery)
33 {
34     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
35 
36     GLint maxClipDistances = 0;
37     glGetIntegerv(GL_MAX_CLIP_DISTANCES_APPLE, &maxClipDistances);
38 
39     EXPECT_GL_NO_ERROR();
40     EXPECT_GE(maxClipDistances, 8);
41 
42     GLboolean enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);
43     EXPECT_GL_NO_ERROR();
44     EXPECT_EQ(enabled, GL_FALSE);
45 
46     glEnable(GL_CLIP_DISTANCE1_APPLE);
47     EXPECT_GL_NO_ERROR();
48     glEnable(GL_CLIP_DISTANCE7_APPLE);
49     EXPECT_GL_NO_ERROR();
50     enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);
51     EXPECT_EQ(enabled, GL_TRUE);
52 
53     glDisable(GL_CLIP_DISTANCE1_APPLE);
54     EXPECT_GL_NO_ERROR();
55     enabled = glIsEnabled(GL_CLIP_DISTANCE1_APPLE);
56     EXPECT_EQ(enabled, GL_FALSE);
57 
58     EXPECT_EQ(glIsEnabled(GL_CLIP_DISTANCE7_APPLE), GL_TRUE);
59 }
60 
61 // Write to one gl_ClipDistance element
TEST_P(ClipDistanceTest,OneClipDistance)62 TEST_P(ClipDistanceTest, OneClipDistance)
63 {
64     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
65 
66     constexpr char kVS[] = R"(
67 #extension GL_APPLE_clip_distance : require
68 
69 uniform vec4 u_plane;
70 
71 attribute vec2 a_position;
72 
73 void main()
74 {
75     gl_Position = vec4(a_position, 0.0, 1.0);
76 
77     gl_ClipDistance[0] = dot(gl_Position, u_plane);
78 })";
79 
80     ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());
81     glLinkProgram(programRed);
82     glUseProgram(programRed);
83     ASSERT_GL_NO_ERROR();
84 
85     glEnable(GL_CLIP_DISTANCE0_APPLE);
86 
87     // Clear to blue
88     glClearColor(0, 0, 1, 1);
89     glClear(GL_COLOR_BUFFER_BIT);
90 
91     // Draw full screen quad with color red
92     glUniform4f(glGetUniformLocation(programRed, "u_plane"), 1, 0, 0, 0.5);
93     EXPECT_GL_NO_ERROR();
94     drawQuad(programRed, "a_position", 0);
95     EXPECT_GL_NO_ERROR();
96 
97     // All pixels on the left of the plane x = -0.5 must be blue
98     for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
99     {
100         for (int y = 0; y < getWindowHeight(); ++y)
101         {
102             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
103         }
104     }
105 
106     // All pixels on the right of the plane x = -0.5 must be red
107     for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth(); ++x)
108     {
109         for (int y = 0; y < getWindowHeight(); ++y)
110         {
111             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
112         }
113     }
114 
115     // Clear to green
116     glClearColor(0, 1, 0, 1);
117     glClear(GL_COLOR_BUFFER_BIT);
118 
119     // Draw full screen quad with color red
120     glUniform4f(glGetUniformLocation(programRed, "u_plane"), -1, 0, 0, -0.5);
121     EXPECT_GL_NO_ERROR();
122     drawQuad(programRed, "a_position", 0);
123     EXPECT_GL_NO_ERROR();
124 
125     // All pixels on the left of the plane x = -0.5 must be red
126     for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
127     {
128         for (int y = 0; y < getWindowHeight(); ++y)
129         {
130             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
131         }
132     }
133 
134     // All pixels on the right of the plane x = -0.5 must be green
135     for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth(); ++x)
136     {
137         for (int y = 0; y < getWindowHeight(); ++y)
138         {
139             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
140         }
141     }
142 
143     // Disable GL_CLIP_DISTANCE
144     glDisable(GL_CLIP_DISTANCE0_APPLE);
145     drawQuad(programRed, "a_position", 0);
146 
147     // All pixels must be red
148     for (int x = 0; x < getWindowWidth(); ++x)
149     {
150         for (int y = 0; y < getWindowHeight(); ++y)
151         {
152             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
153         }
154     }
155 }
156 
157 // Write to 3 clip distances
TEST_P(ClipDistanceTest,ThreeClipDistances)158 TEST_P(ClipDistanceTest, ThreeClipDistances)
159 {
160     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
161 
162     constexpr char kVS[] = R"(
163 #extension GL_APPLE_clip_distance : require
164 
165 uniform vec4 u_plane[3];
166 
167 attribute vec2 a_position;
168 
169 void main()
170 {
171     gl_Position = vec4(a_position, 0.0, 1.0);
172 
173     gl_ClipDistance[0] = dot(gl_Position, u_plane[0]);
174     gl_ClipDistance[3] = dot(gl_Position, u_plane[1]);
175     gl_ClipDistance[7] = dot(gl_Position, u_plane[2]);
176 })";
177 
178     ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());
179     glLinkProgram(programRed);
180     glUseProgram(programRed);
181     ASSERT_GL_NO_ERROR();
182 
183     // Enable 3 clip distances
184     glEnable(GL_CLIP_DISTANCE0_APPLE);
185     glEnable(GL_CLIP_DISTANCE3_APPLE);
186     glEnable(GL_CLIP_DISTANCE7_APPLE);
187     ASSERT_GL_NO_ERROR();
188 
189     // Clear to blue
190     glClearColor(0, 0, 1, 1);
191     glClear(GL_COLOR_BUFFER_BIT);
192 
193     // Draw full screen quad with color red
194     // x = -0.5
195     glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);
196     // x = 0.5
197     glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);
198     // x + y = 1
199     glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);
200     EXPECT_GL_NO_ERROR();
201     drawQuad(programRed, "a_position", 0);
202     EXPECT_GL_NO_ERROR();
203 
204     // All pixels on the left of the plane x = -0.5 must be blue
205     for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
206     {
207         for (int y = 0; y < getWindowHeight(); ++y)
208         {
209             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
210         }
211     }
212 
213     // All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
214     // triangle
215     for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)
216     {
217         for (int y = 0; y < getWindowHeight(); ++y)
218         {
219             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
220         }
221     }
222 
223     for (int y = 0; y < getWindowHeight(); ++y)
224     {
225         for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
226         {
227             if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)
228             {
229                 // bottom left triangle clipped by x=0.5 plane
230                 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
231             }
232             else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)
233             {
234                 // upper right triangle plus right of x=0.5 plane
235                 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
236             }
237         }
238     }
239 
240     // Clear to green
241     glClearColor(0, 1, 0, 1);
242     glClear(GL_COLOR_BUFFER_BIT);
243 
244     // Disable gl_ClipDistance[3]
245     glDisable(GL_CLIP_DISTANCE3_APPLE);
246 
247     // Draw full screen quad with color red
248     EXPECT_GL_NO_ERROR();
249     drawQuad(programRed, "a_position", 0);
250     EXPECT_GL_NO_ERROR();
251 
252     // All pixels on the left of the plane x = -0.5 must be green
253     for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
254     {
255         for (int y = 0; y < getWindowHeight(); ++y)
256         {
257             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
258         }
259     }
260 
261     // All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
262     // triangle
263     for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)
264     {
265         for (int y = 0; y < getWindowHeight(); ++y)
266         {
267             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
268         }
269     }
270 
271     for (int y = 0; y < getWindowHeight(); ++y)
272     {
273         for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
274         {
275             if (x < getWindowWidth() * 3 / 2 - y - 1)
276             {
277                 // bottom left triangle
278                 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
279             }
280             else if (x > getWindowWidth() * 3 / 2 - y + 1)
281             {
282                 // upper right triangle
283                 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
284             }
285         }
286     }
287 }
288 
289 // Redeclare gl_ClipDistance in shader with explitcit size, also use it in a global function
290 // outside main()
TEST_P(ClipDistanceTest,ThreeClipDistancesRedeclared)291 TEST_P(ClipDistanceTest, ThreeClipDistancesRedeclared)
292 {
293     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_APPLE_clip_distance"));
294 
295     constexpr char kVS[] = R"(
296 #extension GL_APPLE_clip_distance : require
297 
298 varying highp float gl_ClipDistance[3];
299 
300 void computeClipDistances(in vec4 position, in vec4 plane[3])
301 {
302     gl_ClipDistance[0] = dot(position, plane[0]);
303     gl_ClipDistance[1] = dot(position, plane[1]);
304     gl_ClipDistance[2] = dot(position, plane[2]);
305 }
306 
307 uniform vec4 u_plane[3];
308 
309 attribute vec2 a_position;
310 
311 void main()
312 {
313     gl_Position = vec4(a_position, 0.0, 1.0);
314 
315     computeClipDistances(gl_Position, u_plane);
316 })";
317 
318     ANGLE_GL_PROGRAM(programRed, kVS, essl1_shaders::fs::Red());
319     glLinkProgram(programRed);
320     glUseProgram(programRed);
321     ASSERT_GL_NO_ERROR();
322 
323     // Enable 3 clip distances
324     glEnable(GL_CLIP_DISTANCE0_APPLE);
325     glEnable(GL_CLIP_DISTANCE1_APPLE);
326     glEnable(GL_CLIP_DISTANCE2_APPLE);
327     ASSERT_GL_NO_ERROR();
328 
329     // Clear to blue
330     glClearColor(0, 0, 1, 1);
331     glClear(GL_COLOR_BUFFER_BIT);
332 
333     // Draw full screen quad with color red
334     // x = -0.5
335     glUniform4f(glGetUniformLocation(programRed, "u_plane[0]"), 1, 0, 0, 0.5);
336     // x = 0.5
337     glUniform4f(glGetUniformLocation(programRed, "u_plane[1]"), -1, 0, 0, 0.5);
338     // x + y = 1
339     glUniform4f(glGetUniformLocation(programRed, "u_plane[2]"), -1, -1, 0, 1);
340     EXPECT_GL_NO_ERROR();
341     drawQuad(programRed, "a_position", 0);
342     EXPECT_GL_NO_ERROR();
343 
344     // All pixels on the left of the plane x = -0.5 must be blue
345     for (int x = 0; x < getWindowWidth() / 4 - 1; ++x)
346     {
347         for (int y = 0; y < getWindowHeight(); ++y)
348         {
349             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
350         }
351     }
352 
353     // All pixels on the right of the plane x = -0.5 must be red, except those in the upper right
354     // triangle
355     for (int x = getWindowWidth() / 4 + 2; x < getWindowWidth() / 2; ++x)
356     {
357         for (int y = 0; y < getWindowHeight(); ++y)
358         {
359             EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
360         }
361     }
362 
363     for (int y = 0; y < getWindowHeight(); ++y)
364     {
365         for (int x = getWindowWidth() / 2; x < getWindowWidth(); ++x)
366         {
367             if (x < getWindowWidth() * 3 / 2 - y - 1 && x < getWindowWidth() * 3 / 4 - 1)
368             {
369                 // bottom left triangle clipped by x=0.5 plane
370                 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::red);
371             }
372             else if (x > getWindowWidth() * 3 / 2 - y + 1 || x > getWindowWidth() * 3 / 4 + 1)
373             {
374                 // upper right triangle plus right of x=0.5 plane
375                 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::blue);
376             }
377         }
378     }
379 }
380 
381 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
382 // tests should be run against.
383 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ClipDistanceTest);
384