• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 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 
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 #include "util/EGLWindow.h"
10 #include "util/random_utils.h"
11 #include "util/test_utils.h"
12 
13 using namespace angle;
14 
15 class OcclusionQueriesTest : public ANGLETest
16 {
17   protected:
OcclusionQueriesTest()18     OcclusionQueriesTest() : mProgram(0), mRNG(1)
19     {
20         setWindowWidth(128);
21         setWindowHeight(128);
22         setConfigRedBits(8);
23         setConfigGreenBits(8);
24         setConfigBlueBits(8);
25         setConfigAlphaBits(8);
26         setConfigDepthBits(24);
27     }
28 
testSetUp()29     void testSetUp() override
30     {
31         mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
32         ASSERT_NE(0u, mProgram);
33     }
34 
testTearDown()35     void testTearDown() override { glDeleteProgram(mProgram); }
36 
37     GLuint mProgram;
38     RNG mRNG;
39 };
40 
41 class OcclusionQueriesTestES3 : public OcclusionQueriesTest
42 {};
43 
TEST_P(OcclusionQueriesTest,IsOccluded)44 TEST_P(OcclusionQueriesTest, IsOccluded)
45 {
46     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
47                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
48 
49     glDepthMask(GL_TRUE);
50     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
51 
52     // draw a quad at depth 0.3
53     glEnable(GL_DEPTH_TEST);
54     glUseProgram(mProgram);
55     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.3f);
56     glUseProgram(0);
57 
58     EXPECT_GL_NO_ERROR();
59 
60     GLQueryEXT query;
61     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
62     drawQuad(mProgram, essl1_shaders::PositionAttrib(),
63              0.8f);  // this quad should be occluded by first quad
64     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
65 
66     EXPECT_GL_NO_ERROR();
67 
68     swapBuffers();
69 
70     GLuint ready = GL_FALSE;
71     while (ready == GL_FALSE)
72     {
73         angle::Sleep(0);
74         glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &ready);
75     }
76 
77     GLuint result = GL_TRUE;
78     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
79 
80     EXPECT_GL_NO_ERROR();
81 
82     EXPECT_GL_FALSE(result);
83 }
84 
TEST_P(OcclusionQueriesTest,IsNotOccluded)85 TEST_P(OcclusionQueriesTest, IsNotOccluded)
86 {
87     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
88                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
89 
90     // TODO(syoussefi): Using render pass ops to clear the framebuffer attachment results in
91     // AMD/Windows misbehaving in this test.  http://anglebug.com/3286
92     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
93 
94     glDepthMask(GL_TRUE);
95     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
96 
97     EXPECT_GL_NO_ERROR();
98 
99     GLQueryEXT query;
100     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
101     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);  // this quad should not be occluded
102     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
103 
104     EXPECT_GL_NO_ERROR();
105 
106     swapBuffers();
107 
108     GLuint result = GL_TRUE;
109     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);  // will block waiting for result
110 
111     EXPECT_GL_NO_ERROR();
112 
113     EXPECT_GL_TRUE(result);
114 }
115 
116 // Test that glClear should not be counted by occlusion query.
TEST_P(OcclusionQueriesTest,ClearNotCounted)117 TEST_P(OcclusionQueriesTest, ClearNotCounted)
118 {
119     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
120                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
121 
122     // TODO(syoussefi): Using render pass ops to clear the framebuffer attachment results in
123     // AMD/Windows misbehaving in this test.  http://anglebug.com/3286
124     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
125 
126     // http://anglebug.com/4925
127     ANGLE_SKIP_TEST_IF(IsD3D11());
128 
129     glDepthMask(GL_TRUE);
130     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
131 
132     EXPECT_GL_NO_ERROR();
133 
134     GLQueryEXT query[2];
135 
136     // First query
137     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[0]);
138     // Full screen clear
139     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
140 
141     // View port clear
142     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
143     glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
144     glEnable(GL_SCISSOR_TEST);
145     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
146 
147     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
148 
149     EXPECT_GL_NO_ERROR();
150 
151     // Second query
152     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[1]);
153 
154     // View port clear
155     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
156 
157     // View port clear
158     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
159     glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
160     glEnable(GL_SCISSOR_TEST);
161     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
162 
163     // this quad should not be occluded
164     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
165 
166     // Clear again
167     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
168 
169     // this quad should not be occluded
170     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 1.0);
171 
172     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
173 
174     EXPECT_GL_NO_ERROR();
175 
176     swapBuffers();
177 
178     GLuint result[2] = {GL_TRUE, GL_TRUE};
179     glGetQueryObjectuivEXT(query[0], GL_QUERY_RESULT_EXT,
180                            &result[0]);  // will block waiting for result
181     glGetQueryObjectuivEXT(query[1], GL_QUERY_RESULT_EXT,
182                            &result[1]);  // will block waiting for result
183     EXPECT_GL_NO_ERROR();
184 
185     EXPECT_GL_FALSE(result[0]);
186     EXPECT_GL_TRUE(result[1]);
187 }
188 
189 // Test that masked glClear should not be counted by occlusion query.
TEST_P(OcclusionQueriesTest,MaskedClearNotCounted)190 TEST_P(OcclusionQueriesTest, MaskedClearNotCounted)
191 {
192     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
193                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
194 
195     // http://anglebug.com/4925
196     ANGLE_SKIP_TEST_IF(IsD3D());
197 
198     GLQueryEXT query;
199 
200     // Masked clear
201     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
202     glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
203     glClear(GL_COLOR_BUFFER_BIT);
204     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
205     EXPECT_GL_NO_ERROR();
206 
207     swapBuffers();
208 
209     GLuint result = GL_TRUE;
210     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
211                            &result);  // will block waiting for result
212     EXPECT_GL_NO_ERROR();
213 
214     EXPECT_GL_FALSE(result);
215 }
216 
217 // Test that copies should not be counted by occlusion query.
TEST_P(OcclusionQueriesTest,CopyNotCounted)218 TEST_P(OcclusionQueriesTest, CopyNotCounted)
219 {
220     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
221                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
222 
223     // http://anglebug.com/4925
224     ANGLE_SKIP_TEST_IF(IsD3D());
225 
226     GLQueryEXT query;
227 
228     // Unrelated draw before the query starts.
229     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
230 
231     // Copy to a texture with a different format from backbuffer
232     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
233     GLTexture tex;
234     glBindTexture(GL_TEXTURE_2D, tex);
235     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, getWindowWidth(), getWindowHeight(), 0);
236     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
237     EXPECT_GL_NO_ERROR();
238 
239     swapBuffers();
240 
241     GLuint result = GL_TRUE;
242     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
243                            &result);  // will block waiting for result
244     EXPECT_GL_NO_ERROR();
245 
246     EXPECT_GL_FALSE(result);
247 }
248 
249 // Test that blit should not be counted by occlusion query.
TEST_P(OcclusionQueriesTestES3,BlitNotCounted)250 TEST_P(OcclusionQueriesTestES3, BlitNotCounted)
251 {
252     // http://anglebug.com/4925
253     ANGLE_SKIP_TEST_IF(IsD3D11());
254 
255     // http://anglebug.com/5101
256     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
257 
258     constexpr GLuint kSize = 64;
259 
260     GLFramebuffer srcFbo;
261     glBindFramebuffer(GL_FRAMEBUFFER, srcFbo);
262 
263     GLTexture srcTex;
264     glBindTexture(GL_TEXTURE_2D, srcTex);
265     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
266     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTex, 0);
267 
268     GLFramebuffer dstFbo;
269     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFbo);
270 
271     GLTexture dstTex;
272     glBindTexture(GL_TEXTURE_2D, dstTex);
273     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kSize, kSize, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
274     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTex, 0);
275 
276     GLQueryEXT query;
277 
278     // Unrelated draw before the query starts.
279     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
280 
281     // Blit flipped and with different formats.
282     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
283     glBlitFramebuffer(0, 0, 64, 64, 64, 64, 0, 0, GL_COLOR_BUFFER_BIT, GL_LINEAR);
284     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
285     EXPECT_GL_NO_ERROR();
286 
287     swapBuffers();
288 
289     GLuint result = GL_TRUE;
290     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
291                            &result);  // will block waiting for result
292     EXPECT_GL_NO_ERROR();
293 
294     EXPECT_GL_FALSE(result);
295 }
296 
297 // Test that multisampled-render-to-texture unresolve should not be counted by occlusion query.
TEST_P(OcclusionQueriesTestES3,UnresolveNotCounted)298 TEST_P(OcclusionQueriesTestES3, UnresolveNotCounted)
299 {
300     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
301 
302     // http://anglebug.com/5086
303     ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
304 
305     constexpr GLuint kSize = 64;
306 
307     GLFramebuffer fboMS;
308     glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
309 
310     // Create multisampled framebuffer to draw into
311     GLTexture textureMS;
312     glBindTexture(GL_TEXTURE_2D, textureMS);
313     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
314     glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
315                                          textureMS, 0, 4);
316 
317     GLRenderbuffer depthMS;
318     glBindRenderbuffer(GL_RENDERBUFFER, depthMS);
319     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, kSize, kSize);
320     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthMS);
321 
322     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
323 
324     // Draw red into the multisampled color buffer.
325     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
326     ASSERT_GL_NO_ERROR();
327 
328     // Create a texture and copy into it, forcing a resolve of the color buffer.
329     GLTexture texture;
330     glBindTexture(GL_TEXTURE_2D, texture);
331     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
332 
333     GLQueryEXT query;
334 
335     // Make a draw call that will fail the depth test, and therefore shouldn't contribute to
336     // occlusion query.
337     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
338     glEnable(GL_DEPTH_TEST);
339     glDepthFunc(GL_NEVER);
340     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f, 0.5f);
341     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
342     EXPECT_GL_NO_ERROR();
343 
344     swapBuffers();
345 
346     GLuint result = GL_TRUE;
347     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT,
348                            &result);  // will block waiting for result
349     EXPECT_GL_NO_ERROR();
350 
351     EXPECT_GL_FALSE(result);
352 }
353 
354 // Test that changing framebuffers work
TEST_P(OcclusionQueriesTest,FramebufferBindingChange)355 TEST_P(OcclusionQueriesTest, FramebufferBindingChange)
356 {
357     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
358                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
359 
360     constexpr GLsizei kSize = 4;
361 
362     // Create two framebuffers, and make sure they are synced.
363     GLFramebuffer fbo[2];
364     GLTexture color[2];
365 
366     for (size_t index = 0; index < 2; ++index)
367     {
368         glBindTexture(GL_TEXTURE_2D, color[index]);
369         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
370                      nullptr);
371 
372         glBindFramebuffer(GL_FRAMEBUFFER, fbo[index]);
373         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color[index],
374                                0);
375 
376         glClearColor(0, index, 1 - index, 1);
377         glClear(GL_COLOR_BUFFER_BIT);
378 
379         EXPECT_PIXEL_COLOR_EQ(0, 0, index ? GLColor::green : GLColor::blue);
380     }
381     EXPECT_GL_NO_ERROR();
382 
383     glViewport(0, 0, kSize, kSize);
384 
385     // Start an occlusion query and issue a draw call to each framebuffer.
386     GLQueryEXT query;
387 
388     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
389 
390     for (size_t index = 0; index < 2; ++index)
391     {
392         glBindFramebuffer(GL_FRAMEBUFFER, fbo[index]);
393         drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
394     }
395 
396     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
397     EXPECT_GL_NO_ERROR();
398 
399     GLuint result = GL_FALSE;
400     glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
401     EXPECT_GL_NO_ERROR();
402 
403     EXPECT_GL_TRUE(result);
404 }
405 
406 // Test multiple occlusion queries.
TEST_P(OcclusionQueriesTest,MultiQueries)407 TEST_P(OcclusionQueriesTest, MultiQueries)
408 {
409     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
410                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
411 
412     // TODO(syoussefi): Using render pass ops to clear the framebuffer attachment results in
413     // AMD/Windows misbehaving in this test.  http://anglebug.com/3286
414     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
415 
416     // http://anglebug.com/4925
417     ANGLE_SKIP_TEST_IF(IsOpenGL() || IsD3D11());
418 
419     // TODO(anglebug.com/5360): Failing on ARM-based Apple DTKs.
420     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsDesktopOpenGL());
421 
422     GLQueryEXT query[5];
423 
424     // First query
425     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[0]);
426 
427     EXPECT_GL_NO_ERROR();
428 
429     glEnable(GL_DEPTH_TEST);
430     glDepthMask(GL_TRUE);
431     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
432 
433     EXPECT_GL_NO_ERROR();
434 
435     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);  // this quad should not be occluded
436 
437     EXPECT_GL_NO_ERROR();
438 
439     // Due to implementation might skip in-renderpass flush, we are using glFinish here to force a
440     // flush. A flush shound't clear the query result.
441     glFinish();
442 
443     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
444     drawQuad(mProgram, essl1_shaders::PositionAttrib(), -2, 0.25f);  // this quad should be occluded
445     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
446     // First query ends
447 
448     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f,
449              0.25f);  // this quad should not be occluded
450 
451     // Second query
452     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[1]);
453     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
454              0.25f);  // this quad should be occluded
455     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
456 
457     // Third query
458     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[2]);
459     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
460              0.5f);  // this quad should not be occluded
461     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
462     // ------------
463     glFinish();
464 
465     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
466     glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
467     glEnable(GL_SCISSOR_TEST);
468     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
469              0.5f);  // this quad should not be occluded
470 
471     // Fourth query: begin query then end then begin again
472     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[3]);
473     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
474              1);  // this quad should not be occluded
475     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
476     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[3]);
477     EXPECT_GL_NO_ERROR();
478     // glClear should not be counted toward query);
479     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
480     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
481 
482     // Fifth query spans across frames
483     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query[4]);
484     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f,
485              0.25f);  // this quad should not be occluded
486 
487     swapBuffers();
488 
489     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
490 
491     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.9f,
492              0.5f);  // this quad should not be occluded
493     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
494 
495     GLuint result = GL_TRUE;
496     glGetQueryObjectuivEXT(query[0], GL_QUERY_RESULT_EXT,
497                            &result);  // will block waiting for result
498     EXPECT_GL_NO_ERROR();
499     EXPECT_GL_TRUE(result);
500 
501     glGetQueryObjectuivEXT(query[1], GL_QUERY_RESULT_EXT,
502                            &result);  // will block waiting for result
503     EXPECT_GL_NO_ERROR();
504     EXPECT_GL_FALSE(result);
505 
506     glGetQueryObjectuivEXT(query[2], GL_QUERY_RESULT_EXT,
507                            &result);  // will block waiting for result
508     EXPECT_GL_NO_ERROR();
509     EXPECT_GL_TRUE(result);
510 
511     glGetQueryObjectuivEXT(query[3], GL_QUERY_RESULT_EXT,
512                            &result);  // will block waiting for result
513     EXPECT_GL_NO_ERROR();
514     EXPECT_GL_FALSE(result);
515 
516     glGetQueryObjectuivEXT(query[4], GL_QUERY_RESULT_EXT,
517                            &result);  // will block waiting for result
518     EXPECT_GL_NO_ERROR();
519     EXPECT_GL_TRUE(result);
520 }
521 
TEST_P(OcclusionQueriesTest,Errors)522 TEST_P(OcclusionQueriesTest, Errors)
523 {
524     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
525                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
526 
527     glDepthMask(GL_TRUE);
528     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
529 
530     EXPECT_GL_NO_ERROR();
531 
532     GLuint query  = 0;
533     GLuint query2 = 0;
534     glGenQueriesEXT(1, &query);
535 
536     EXPECT_GL_FALSE(glIsQueryEXT(query));
537     EXPECT_GL_FALSE(glIsQueryEXT(query2));
538 
539     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0);  // can't pass 0 as query id
540     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
541 
542     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
543     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
544                     query2);  // can't initiate a query while one's already active
545     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
546 
547     EXPECT_GL_TRUE(glIsQueryEXT(query));
548     EXPECT_GL_FALSE(glIsQueryEXT(query2));  // have not called begin
549 
550     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.8f);  // this quad should not be occluded
551     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);      // no active query for this target
552     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
553     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
554 
555     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
556                     query);  // can't begin a query as a different type than previously used
557     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
558 
559     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
560                     query2);  // have to call genqueries first
561     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
562 
563     glGenQueriesEXT(1, &query2);
564     glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, query2);  // should be ok now
565     EXPECT_GL_TRUE(glIsQueryEXT(query2));
566 
567     drawQuad(mProgram, essl1_shaders::PositionAttrib(),
568              0.3f);                  // this should draw in front of other quad
569     glDeleteQueriesEXT(1, &query2);  // should delete when query becomes inactive
570     glEndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);  // should not incur error; should delete
571                                                             // query + 1 at end of execution.
572     EXPECT_GL_NO_ERROR();
573 
574     swapBuffers();
575 
576     EXPECT_GL_NO_ERROR();
577 
578     GLuint ready = GL_FALSE;
579     glGetQueryObjectuivEXT(query2, GL_QUERY_RESULT_AVAILABLE_EXT,
580                            &ready);  // this query is now deleted
581     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
582 
583     EXPECT_GL_NO_ERROR();
584 }
585 
586 // Test that running multiple simultaneous queries from multiple EGL contexts returns the correct
587 // result for each query.  Helps expose bugs in ANGLE's virtual contexts.
TEST_P(OcclusionQueriesTest,MultiContext)588 TEST_P(OcclusionQueriesTest, MultiContext)
589 {
590     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
591                        !IsGLExtensionEnabled("GL_EXT_occlusion_query_boolean"));
592 
593     // TODO(cwallez@chromium.org): Suppression for http://anglebug.com/3080
594     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
595 
596     // Test skipped because the D3D backends cannot support simultaneous queries on multiple
597     // contexts yet.
598     ANGLE_SKIP_TEST_IF(GetParam() == ES2_D3D9() || GetParam() == ES2_D3D11() ||
599                        GetParam() == ES3_D3D11());
600 
601     glDepthMask(GL_TRUE);
602     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
603 
604     // draw a quad at depth 0.5
605     glEnable(GL_DEPTH_TEST);
606     drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
607 
608     EGLWindow *window = getEGLWindow();
609 
610     EGLDisplay display = window->getDisplay();
611     EGLConfig config   = window->getConfig();
612     EGLSurface surface = window->getSurface();
613 
614     EGLint contextAttributes[] = {
615         EGL_CONTEXT_MAJOR_VERSION_KHR,
616         GetParam().majorVersion,
617         EGL_CONTEXT_MINOR_VERSION_KHR,
618         GetParam().minorVersion,
619         EGL_NONE,
620     };
621 
622     const size_t passCount = 5;
623     struct ContextInfo
624     {
625         EGLContext context;
626         GLuint program;
627         GLuint query;
628         bool visiblePasses[passCount];
629         bool shouldPass;
630     };
631 
632     ContextInfo contexts[] = {
633         {
634             EGL_NO_CONTEXT,
635             0,
636             0,
637             {false, false, false, false, false},
638             false,
639         },
640         {
641             EGL_NO_CONTEXT,
642             0,
643             0,
644             {false, true, false, true, false},
645             true,
646         },
647         {
648             EGL_NO_CONTEXT,
649             0,
650             0,
651             {false, false, false, false, false},
652             false,
653         },
654         {
655             EGL_NO_CONTEXT,
656             0,
657             0,
658             {true, true, false, true, true},
659             true,
660         },
661         {
662             EGL_NO_CONTEXT,
663             0,
664             0,
665             {false, true, true, true, true},
666             true,
667         },
668         {
669             EGL_NO_CONTEXT,
670             0,
671             0,
672             {true, false, false, true, false},
673             true,
674         },
675         {
676             EGL_NO_CONTEXT,
677             0,
678             0,
679             {false, false, false, false, false},
680             false,
681         },
682         {
683             EGL_NO_CONTEXT,
684             0,
685             0,
686             {false, false, false, false, false},
687             false,
688         },
689     };
690 
691     for (auto &context : contexts)
692     {
693         context.context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
694         ASSERT_NE(context.context, EGL_NO_CONTEXT);
695 
696         eglMakeCurrent(display, surface, surface, context.context);
697 
698         context.program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
699         ASSERT_NE(context.program, 0u);
700 
701         glDepthMask(GL_FALSE);
702         glEnable(GL_DEPTH_TEST);
703 
704         glGenQueriesEXT(1, &context.query);
705         glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, context.query);
706 
707         ASSERT_GL_NO_ERROR();
708     }
709 
710     for (size_t pass = 0; pass < passCount; pass++)
711     {
712         for (const auto &context : contexts)
713         {
714             eglMakeCurrent(display, surface, surface, context.context);
715 
716             float depth = context.visiblePasses[pass] ? mRNG.randomFloatBetween(0.0f, 0.4f)
717                                                       : mRNG.randomFloatBetween(0.6f, 1.0f);
718             drawQuad(context.program, essl1_shaders::PositionAttrib(), depth);
719 
720             EXPECT_GL_NO_ERROR();
721         }
722     }
723 
724     for (const auto &context : contexts)
725     {
726         eglMakeCurrent(display, surface, surface, context.context);
727         glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
728 
729         GLuint result = GL_TRUE;
730         glGetQueryObjectuivEXT(context.query, GL_QUERY_RESULT_EXT, &result);
731 
732         EXPECT_GL_NO_ERROR();
733 
734         GLuint expectation = context.shouldPass ? GL_TRUE : GL_FALSE;
735         EXPECT_EQ(expectation, result);
736     }
737 
738     eglMakeCurrent(display, surface, surface, window->getContext());
739 
740     for (auto &context : contexts)
741     {
742         eglDestroyContext(display, context.context);
743         context.context = EGL_NO_CONTEXT;
744     }
745 }
746 
747 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(OcclusionQueriesTest);
748 
749 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OcclusionQueriesTestES3);
750 ANGLE_INSTANTIATE_TEST_ES3(OcclusionQueriesTestES3);
751