1 //
2 // Copyright 2021 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 // EGLBufferAgeTest.cpp:
7 // EGL extension EGL_EXT_buffer_age
8 //
9
10 #include <gtest/gtest.h>
11
12 #include "test_utils/ANGLETest.h"
13 #include "util/EGLWindow.h"
14 #include "util/OSWindow.h"
15
16 using namespace angle;
17
18 class EGLBufferAgeTest : public ANGLETest<>
19 {
20 public:
EGLBufferAgeTest()21 EGLBufferAgeTest() : mDisplay(EGL_NO_DISPLAY) {}
22
testSetUp()23 void testSetUp() override
24 {
25 EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
26 mDisplay = eglGetPlatformDisplayEXT(
27 EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
28 EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY);
29 EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
30 mMajorVersion = GetParam().majorVersion;
31 mExtensionSupported = IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_buffer_age");
32 }
33
testTearDown()34 void testTearDown() override
35 {
36 if (mDisplay != EGL_NO_DISPLAY)
37 {
38 eglTerminate(mDisplay);
39 eglReleaseThread();
40 mDisplay = EGL_NO_DISPLAY;
41 }
42 ASSERT_EGL_SUCCESS() << "Error during test TearDown";
43 }
44
chooseConfig(EGLConfig * config) const45 virtual bool chooseConfig(EGLConfig *config) const
46 {
47 bool result = false;
48 EGLint count = 0;
49 EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
50 EGLint attribs[] = {EGL_RED_SIZE,
51 8,
52 EGL_GREEN_SIZE,
53 8,
54 EGL_BLUE_SIZE,
55 8,
56 EGL_ALPHA_SIZE,
57 0,
58 EGL_RENDERABLE_TYPE,
59 clientVersion,
60 EGL_SURFACE_TYPE,
61 EGL_WINDOW_BIT,
62 EGL_NONE};
63
64 result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
65 EXPECT_EGL_TRUE(result && (count > 0));
66 return result;
67 }
68
createContext(EGLConfig config,EGLContext * context)69 bool createContext(EGLConfig config, EGLContext *context)
70 {
71 bool result = false;
72 EGLint attribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE};
73
74 *context = eglCreateContext(mDisplay, config, nullptr, attribs);
75 result = (*context != EGL_NO_CONTEXT);
76 EXPECT_TRUE(result);
77 return result;
78 }
79
createWindowSurface(EGLConfig config,EGLNativeWindowType win,EGLSurface * surface) const80 bool createWindowSurface(EGLConfig config, EGLNativeWindowType win, EGLSurface *surface) const
81 {
82 bool result = false;
83 EGLint attribs[] = {EGL_NONE};
84
85 *surface = eglCreateWindowSurface(mDisplay, config, win, attribs);
86 result = (*surface != EGL_NO_SURFACE);
87 EXPECT_TRUE(result);
88 return result;
89 }
90
queryAge(EGLSurface surface) const91 EGLint queryAge(EGLSurface surface) const
92 {
93 EGLint age = 0;
94 bool result = eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &age);
95 EXPECT_TRUE(result);
96 return age;
97 }
98
queryAgeAttribKHR(EGLSurface surface) const99 EGLint queryAgeAttribKHR(EGLSurface surface) const
100 {
101 EGLAttribKHR age = 0;
102 bool result = eglQuerySurface64KHR(mDisplay, surface, EGL_BUFFER_AGE_EXT, &age);
103 EXPECT_TRUE(result);
104 return age;
105 }
106
107 EGLDisplay mDisplay = EGL_NO_DISPLAY;
108 EGLint mMajorVersion = 0;
109 const EGLint kWidth = 64;
110 const EGLint kHeight = 64;
111 bool mExtensionSupported = false;
112 };
113
114 class EGLBufferAgeTest_MSAA : public EGLBufferAgeTest
115 {
116 public:
EGLBufferAgeTest_MSAA()117 EGLBufferAgeTest_MSAA() : EGLBufferAgeTest() {}
118
chooseConfig(EGLConfig * config) const119 bool chooseConfig(EGLConfig *config) const override
120 {
121 bool result = false;
122 EGLint count = 0;
123 EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
124 EGLint attribs[] = {EGL_RED_SIZE,
125 8,
126 EGL_GREEN_SIZE,
127 8,
128 EGL_BLUE_SIZE,
129 8,
130 EGL_ALPHA_SIZE,
131 8,
132 EGL_RENDERABLE_TYPE,
133 clientVersion,
134 EGL_SAMPLE_BUFFERS,
135 1,
136 EGL_SAMPLES,
137 4,
138 EGL_SURFACE_TYPE,
139 EGL_WINDOW_BIT,
140 EGL_NONE};
141
142 result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
143 EXPECT_EGL_TRUE(result && (count > 0));
144 return result;
145 }
146 };
147
148 class EGLBufferAgeTest_MSAA_DS : public EGLBufferAgeTest
149 {
150 public:
EGLBufferAgeTest_MSAA_DS()151 EGLBufferAgeTest_MSAA_DS() : EGLBufferAgeTest() {}
152
chooseConfig(EGLConfig * config) const153 bool chooseConfig(EGLConfig *config) const override
154 {
155 bool result = false;
156 EGLint count = 0;
157 EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
158 EGLint attribs[] = {EGL_RED_SIZE,
159 8,
160 EGL_GREEN_SIZE,
161 8,
162 EGL_BLUE_SIZE,
163 8,
164 EGL_ALPHA_SIZE,
165 8,
166 EGL_DEPTH_SIZE,
167 8,
168 EGL_STENCIL_SIZE,
169 8,
170 EGL_RENDERABLE_TYPE,
171 clientVersion,
172 EGL_SAMPLE_BUFFERS,
173 1,
174 EGL_SAMPLES,
175 4,
176 EGL_SURFACE_TYPE,
177 EGL_WINDOW_BIT,
178 EGL_NONE};
179
180 result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
181 EXPECT_EGL_TRUE(result && (count > 0));
182 return result;
183 }
184 };
185
186 // Query for buffer age
TEST_P(EGLBufferAgeTest,QueryBufferAge)187 TEST_P(EGLBufferAgeTest, QueryBufferAge)
188 {
189 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
190
191 const bool lockSurface3ExtSupported =
192 IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_lock_surface3");
193
194 EGLConfig config = EGL_NO_CONFIG_KHR;
195 EXPECT_TRUE(chooseConfig(&config));
196
197 EGLContext context = EGL_NO_CONTEXT;
198 EXPECT_TRUE(createContext(config, &context));
199 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
200
201 EGLSurface surface = EGL_NO_SURFACE;
202
203 OSWindow *osWindow = OSWindow::New();
204 osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
205 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
206 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
207
208 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
209 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
210
211 glClearColor(1.0, 0.0, 0.0, 1.0);
212
213 const uint32_t loopcount = 15;
214 EGLint expectedAge = 0;
215 for (uint32_t i = 0; i < loopcount; i++)
216 {
217 // Alternate between eglQuerySurface and eglQuerySurface64KHR
218 EGLint age = -1;
219 if (i % 2 == 0 || !lockSurface3ExtSupported)
220 {
221 age = queryAge(surface);
222 }
223 else
224 {
225 age = static_cast<EGLint>(queryAgeAttribKHR(surface));
226 }
227
228 // Should start with zero age and then flip to buffer count - which we don't know.
229 if ((expectedAge == 0) && (age > 0))
230 {
231 expectedAge = age;
232 }
233 EXPECT_EQ(age, expectedAge);
234
235 glClear(GL_COLOR_BUFFER_BIT);
236 ASSERT_GL_NO_ERROR() << "glClear failed";
237 eglSwapBuffers(mDisplay, surface);
238 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
239 }
240
241 EXPECT_GT(expectedAge, 0);
242
243 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
244 ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
245
246 eglDestroySurface(mDisplay, surface);
247 surface = EGL_NO_SURFACE;
248 osWindow->destroy();
249 OSWindow::Delete(&osWindow);
250
251 eglDestroyContext(mDisplay, context);
252 context = EGL_NO_CONTEXT;
253 }
254
255 // Verify contents of buffer are as expected
TEST_P(EGLBufferAgeTest,VerifyContents)256 TEST_P(EGLBufferAgeTest, VerifyContents)
257 {
258 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
259
260 EGLConfig config = EGL_NO_CONFIG_KHR;
261 EXPECT_TRUE(chooseConfig(&config));
262
263 EGLContext context = EGL_NO_CONTEXT;
264 EXPECT_TRUE(createContext(config, &context));
265 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
266
267 EGLSurface surface = EGL_NO_SURFACE;
268
269 OSWindow *osWindow = OSWindow::New();
270 osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
271 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
272 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
273
274 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
275 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
276
277 const angle::GLColor kLightGray(191, 191, 191, 255); // 0.75
278 const angle::GLColor kDarkGray(64, 64, 64, 255); // 0.25
279 const angle::GLColor kColorSet[] = {
280 GLColor::blue, GLColor::cyan, kDarkGray, GLColor::green, GLColor::red,
281 GLColor::white, GLColor::yellow, GLColor::black, GLColor::magenta, kLightGray,
282 GLColor::black, // Extra loops until color cycled through
283 GLColor::black, GLColor::black, GLColor::black, GLColor::black};
284
285 EGLint age = 0;
286 angle::GLColor expectedColor = GLColor::black;
287 int loopCount = (sizeof(kColorSet) / sizeof(kColorSet[0]));
288 for (int i = 0; i < loopCount; i++)
289 {
290 age = queryAge(surface);
291 if (age > 0)
292 {
293 // Check that color/content is what we expect
294 expectedColor = kColorSet[i - age];
295 EXPECT_PIXEL_COLOR_EQ(1, 1, expectedColor);
296 }
297
298 float red = kColorSet[i].R / 255.0;
299 float green = kColorSet[i].G / 255.0;
300 float blue = kColorSet[i].B / 255.0;
301 float alpha = kColorSet[i].A / 255.0;
302
303 glClearColor(red, green, blue, alpha);
304 glClear(GL_COLOR_BUFFER_BIT);
305 ASSERT_GL_NO_ERROR() << "glClear failed";
306 eglSwapBuffers(mDisplay, surface);
307 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
308 }
309
310 EXPECT_GT(age, 0);
311
312 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
313 ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
314
315 eglDestroySurface(mDisplay, surface);
316 surface = EGL_NO_SURFACE;
317 osWindow->destroy();
318 OSWindow::Delete(&osWindow);
319
320 eglDestroyContext(mDisplay, context);
321 context = EGL_NO_CONTEXT;
322 }
323
324 // Verify contents of buffer are as expected for a multisample image
TEST_P(EGLBufferAgeTest_MSAA,VerifyContentsForMultisampled)325 TEST_P(EGLBufferAgeTest_MSAA, VerifyContentsForMultisampled)
326 {
327 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
328
329 EGLConfig config = EGL_NO_CONFIG_KHR;
330 EXPECT_TRUE(chooseConfig(&config));
331
332 EGLContext context = EGL_NO_CONTEXT;
333 EXPECT_TRUE(createContext(config, &context));
334 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
335
336 EGLSurface surface = EGL_NO_SURFACE;
337
338 OSWindow *osWindow = OSWindow::New();
339 osWindow->initialize("EGLBufferAgeTest_MSAA", kWidth, kHeight);
340 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
341 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
342
343 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
344 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
345
346 std::vector<angle::GLColor> kColorSet;
347 for (uint32_t i = 0; i < 16; i++)
348 {
349 kColorSet.emplace_back(i * 10, 0, 0, 255);
350 }
351
352 // Set up
353 glClearColor(0, 0, 0, 0);
354 glClearDepthf(0.0);
355 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
356
357 EGLint age = 0;
358 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
359 GLint colorLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
360
361 for (size_t i = 0; i < kColorSet.size(); i++)
362 {
363 age = queryAge(surface);
364 if (age > 0)
365 {
366 // Check that color/content is what we expect
367 angle::GLColor expectedColor = kColorSet[i - age];
368 EXPECT_PIXEL_COLOR_EQ(1, 1, expectedColor);
369 }
370 glBindFramebuffer(GL_FRAMEBUFFER, 0);
371 glUseProgram(program);
372 glUniform4fv(colorLocation, 1, kColorSet[i].toNormalizedVector().data());
373 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
374
375 eglSwapBuffers(mDisplay, surface);
376 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
377 }
378
379 EXPECT_GE(age, 0);
380
381 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
382 ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
383
384 eglDestroySurface(mDisplay, surface);
385 surface = EGL_NO_SURFACE;
386 osWindow->destroy();
387 OSWindow::Delete(&osWindow);
388
389 eglDestroyContext(mDisplay, context);
390 context = EGL_NO_CONTEXT;
391 }
392
393 // Verify contents of buffer are as expected for a multisample image with depth/stencil enabled
TEST_P(EGLBufferAgeTest_MSAA_DS,VerifyContentsForMultisampledWithDepthStencil)394 TEST_P(EGLBufferAgeTest_MSAA_DS, VerifyContentsForMultisampledWithDepthStencil)
395 {
396 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
397
398 EGLConfig config = EGL_NO_CONFIG_KHR;
399 EXPECT_TRUE(chooseConfig(&config));
400
401 EGLContext context = EGL_NO_CONTEXT;
402 EXPECT_TRUE(createContext(config, &context));
403 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
404
405 EGLSurface surface = EGL_NO_SURFACE;
406
407 OSWindow *osWindow = OSWindow::New();
408 osWindow->initialize("EGLBufferAgeTest_MSAA", kWidth, kHeight);
409 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
410 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
411
412 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
413 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
414
415 std::vector<angle::GLColor> kColorSet;
416 for (uint32_t i = 0; i < 16; i++)
417 {
418 kColorSet.emplace_back(i * 10, 0, 0, 255);
419 }
420
421 // Set up
422 glClearColor(0, 0, 0, 0);
423 glClearDepthf(0.0);
424 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
425
426 EGLint age = 0;
427 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
428 GLint colorLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
429
430 for (size_t i = 0; i < kColorSet.size(); i++)
431 {
432 age = queryAge(surface);
433 if (age > 0)
434 {
435 // Check that color/content is what we expect
436 angle::GLColor expectedColor = kColorSet[i - age];
437 EXPECT_PIXEL_COLOR_EQ(1, 1, expectedColor);
438 }
439 glBindFramebuffer(GL_FRAMEBUFFER, 0);
440 glUseProgram(program);
441 glUniform4fv(colorLocation, 1, kColorSet[i].toNormalizedVector().data());
442 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
443
444 eglSwapBuffers(mDisplay, surface);
445 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
446 }
447
448 EXPECT_GE(age, 0);
449
450 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
451 ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
452
453 eglDestroySurface(mDisplay, surface);
454 surface = EGL_NO_SURFACE;
455 osWindow->destroy();
456 OSWindow::Delete(&osWindow);
457
458 eglDestroyContext(mDisplay, context);
459 context = EGL_NO_CONTEXT;
460 }
461
462 // Verify EGL_BAD_SURFACE when not current
TEST_P(EGLBufferAgeTest,UncurrentContextBadSurface)463 TEST_P(EGLBufferAgeTest, UncurrentContextBadSurface)
464 {
465 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
466
467 EGLConfig config = EGL_NO_CONFIG_KHR;
468 EXPECT_TRUE(chooseConfig(&config));
469
470 EGLContext context = EGL_NO_CONTEXT;
471 EXPECT_TRUE(createContext(config, &context));
472 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
473
474 EGLSurface surface = EGL_NO_SURFACE;
475
476 OSWindow *osWindow = OSWindow::New();
477 osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
478 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
479 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
480
481 // No current context
482
483 EGLint value = 0;
484 EXPECT_EGL_FALSE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &value));
485 EXPECT_EGL_ERROR(EGL_BAD_SURFACE);
486
487 EGLContext otherContext = EGL_NO_CONTEXT;
488 EXPECT_TRUE(createContext(config, &otherContext));
489 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
490
491 // Surface current to another context
492 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, otherContext));
493 // Make context the active context
494 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
495
496 value = 0;
497 EXPECT_EGL_FALSE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &value));
498 EXPECT_EGL_ERROR(EGL_BAD_SURFACE);
499
500 eglDestroySurface(mDisplay, surface);
501 surface = EGL_NO_SURFACE;
502 osWindow->destroy();
503 OSWindow::Delete(&osWindow);
504
505 eglDestroyContext(mDisplay, otherContext);
506 otherContext = EGL_NO_CONTEXT;
507
508 eglDestroyContext(mDisplay, context);
509 context = EGL_NO_CONTEXT;
510 }
511
512 // Expect age always == 1 when EGL_BUFFER_PRESERVED is chosen
TEST_P(EGLBufferAgeTest,BufferPreserved)513 TEST_P(EGLBufferAgeTest, BufferPreserved)
514 {
515 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
516
517 EGLConfig config = EGL_NO_CONFIG_KHR;
518 EGLint count = 0;
519 EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
520 EGLint attribs[] = {EGL_RED_SIZE,
521 8,
522 EGL_GREEN_SIZE,
523 8,
524 EGL_BLUE_SIZE,
525 8,
526 EGL_ALPHA_SIZE,
527 0,
528 EGL_RENDERABLE_TYPE,
529 clientVersion,
530 EGL_SURFACE_TYPE,
531 EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
532 EGL_NONE};
533
534 EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count));
535 // Skip if no configs, this indicates EGL_BUFFER_PRESERVED is not supported.
536 ANGLE_SKIP_TEST_IF(count == 0);
537
538 EGLContext context = EGL_NO_CONTEXT;
539 EXPECT_TRUE(createContext(config, &context));
540 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
541
542 EGLSurface surface = EGL_NO_SURFACE;
543
544 OSWindow *osWindow = OSWindow::New();
545 osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
546 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
547 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
548
549 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
550 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
551
552 glClearColor(1.0, 0.0, 0.0, 1.0);
553
554 const uint32_t loopcount = 10;
555 EGLint expectedAge = 1;
556 for (uint32_t i = 0; i < loopcount; i++)
557 {
558 EGLint age = queryAge(surface);
559 EXPECT_EQ(age, expectedAge);
560
561 glClear(GL_COLOR_BUFFER_BIT);
562 ASSERT_GL_NO_ERROR() << "glClear failed";
563 eglSwapBuffers(mDisplay, surface);
564 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
565 }
566
567 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
568 ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
569
570 eglDestroySurface(mDisplay, surface);
571 surface = EGL_NO_SURFACE;
572 osWindow->destroy();
573 OSWindow::Delete(&osWindow);
574
575 eglDestroyContext(mDisplay, context);
576 context = EGL_NO_CONTEXT;
577 }
578
579 // Expect age always == 0 when EGL_SINGLE_BUFFER is chosen
TEST_P(EGLBufferAgeTest,SingleBuffer)580 TEST_P(EGLBufferAgeTest, SingleBuffer)
581 {
582 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
583 ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
584
585 EGLConfig config = EGL_NO_CONFIG_KHR;
586 EGLint count = 0;
587 EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
588 EGLint attribs[] = {EGL_RED_SIZE,
589 8,
590 EGL_GREEN_SIZE,
591 8,
592 EGL_BLUE_SIZE,
593 8,
594 EGL_ALPHA_SIZE,
595 0,
596 EGL_RENDERABLE_TYPE,
597 clientVersion,
598 EGL_SURFACE_TYPE,
599 EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR,
600 EGL_NONE};
601
602 EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count));
603 // Skip if no configs, this indicates EGL_SINGLE_BUFFER is not supported.
604 ANGLE_SKIP_TEST_IF(count == 0);
605
606 EGLContext context = EGL_NO_CONTEXT;
607 EXPECT_TRUE(createContext(config, &context));
608 ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
609
610 EGLSurface surface = EGL_NO_SURFACE;
611
612 OSWindow *osWindow = OSWindow::New();
613 osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
614 EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
615 ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
616
617 EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
618 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
619
620 // Set render buffer to EGL_SINGLE_BUFFER
621 EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
622
623 glClearColor(1.0, 0.0, 0.0, 1.0);
624
625 // Expect age = 0 before first eglSwapBuffers() call
626 EGLint age = queryAge(surface);
627 EXPECT_EQ(age, 0);
628 eglSwapBuffers(mDisplay, surface);
629 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
630
631 const uint32_t loopcount = 10;
632 EGLint expectedAge = 0;
633 for (uint32_t i = 0; i < loopcount; i++)
634 {
635 age = queryAge(surface);
636 EXPECT_EQ(age, expectedAge);
637
638 glClear(GL_COLOR_BUFFER_BIT);
639 ASSERT_GL_NO_ERROR() << "glClear failed";
640 eglSwapBuffers(mDisplay, surface);
641 ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
642 }
643
644 EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
645 ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
646
647 eglDestroySurface(mDisplay, surface);
648 surface = EGL_NO_SURFACE;
649 osWindow->destroy();
650 OSWindow::Delete(&osWindow);
651
652 eglDestroyContext(mDisplay, context);
653 context = EGL_NO_CONTEXT;
654 }
655
656 ANGLE_INSTANTIATE_TEST(EGLBufferAgeTest,
657 WithNoFixture(ES2_METAL()),
658 WithNoFixture(ES3_METAL()),
659 WithNoFixture(ES2_OPENGLES()),
660 WithNoFixture(ES3_OPENGLES()),
661 WithNoFixture(ES2_OPENGL()),
662 WithNoFixture(ES3_OPENGL()),
663 WithNoFixture(ES2_VULKAN()),
664 WithNoFixture(ES3_VULKAN()));
665 ANGLE_INSTANTIATE_TEST(EGLBufferAgeTest_MSAA,
666 WithNoFixture(ES2_METAL()),
667 WithNoFixture(ES3_METAL()),
668 WithNoFixture(ES2_OPENGLES()),
669 WithNoFixture(ES3_OPENGLES()),
670 WithNoFixture(ES2_OPENGL()),
671 WithNoFixture(ES3_OPENGL()),
672 WithNoFixture(ES2_VULKAN()),
673 WithNoFixture(ES3_VULKAN()));
674 ANGLE_INSTANTIATE_TEST(EGLBufferAgeTest_MSAA_DS,
675 WithNoFixture(ES2_METAL()),
676 WithNoFixture(ES3_METAL()),
677 WithNoFixture(ES2_OPENGLES()),
678 WithNoFixture(ES3_OPENGLES()),
679 WithNoFixture(ES2_OPENGL()),
680 WithNoFixture(ES3_OPENGL()),
681 WithNoFixture(ES2_VULKAN()),
682 WithNoFixture(ES3_VULKAN()));
683