xref: /aosp_15_r20/external/angle/src/tests/egl_tests/EGLBufferAgeTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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