blob: d914e510283fcd32ed29c06959bb1fe666b09120 [file] [log] [blame]
//
// Copyright 2021 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EGLBufferAgeTest.cpp:
// EGL extension EGL_EXT_buffer_age
//
#include <gtest/gtest.h>
#include "test_utils/ANGLETest.h"
#include "util/EGLWindow.h"
#include "util/OSWindow.h"
using namespace angle;
class EGLBufferAgeTest : public ANGLETest<>
{
public:
EGLBufferAgeTest() : mDisplay(EGL_NO_DISPLAY) {}
void testSetUp() override
{
EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
mDisplay = eglGetPlatformDisplayEXT(
EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY);
EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
mMajorVersion = GetParam().majorVersion;
mExtensionSupported = IsEGLDisplayExtensionEnabled(mDisplay, "EGL_EXT_buffer_age");
}
void testTearDown() override
{
if (mDisplay != EGL_NO_DISPLAY)
{
eglTerminate(mDisplay);
eglReleaseThread();
mDisplay = EGL_NO_DISPLAY;
}
ASSERT_EGL_SUCCESS() << "Error during test TearDown";
}
virtual bool chooseConfig(EGLConfig *config) const
{
bool result = false;
EGLint count = 0;
EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
EGLint attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
0,
EGL_RENDERABLE_TYPE,
clientVersion,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_NONE};
result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
EXPECT_EGL_TRUE(result && (count > 0));
return result;
}
bool createContext(EGLConfig config, EGLContext *context)
{
bool result = false;
EGLint attribs[] = {EGL_CONTEXT_MAJOR_VERSION, mMajorVersion, EGL_NONE};
*context = eglCreateContext(mDisplay, config, nullptr, attribs);
result = (*context != EGL_NO_CONTEXT);
EXPECT_TRUE(result);
return result;
}
bool createWindowSurface(EGLConfig config, EGLNativeWindowType win, EGLSurface *surface) const
{
bool result = false;
EGLint attribs[] = {EGL_NONE};
*surface = eglCreateWindowSurface(mDisplay, config, win, attribs);
result = (*surface != EGL_NO_SURFACE);
EXPECT_TRUE(result);
return result;
}
EGLint queryAge(EGLSurface surface) const
{
EGLint age = 0;
bool result = eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &age);
EXPECT_TRUE(result);
return age;
}
EGLint queryAgeAttribKHR(EGLSurface surface) const
{
EGLAttribKHR age = 0;
bool result = eglQuerySurface64KHR(mDisplay, surface, EGL_BUFFER_AGE_EXT, &age);
EXPECT_TRUE(result);
return age;
}
EGLDisplay mDisplay = EGL_NO_DISPLAY;
EGLint mMajorVersion = 0;
const EGLint kWidth = 64;
const EGLint kHeight = 64;
bool mExtensionSupported = false;
};
class EGLBufferAgeTest_MSAA : public EGLBufferAgeTest
{
public:
EGLBufferAgeTest_MSAA() : EGLBufferAgeTest() {}
bool chooseConfig(EGLConfig *config) const override
{
bool result = false;
EGLint count = 0;
EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
EGLint attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_RENDERABLE_TYPE,
clientVersion,
EGL_SAMPLE_BUFFERS,
1,
EGL_SAMPLES,
4,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_NONE};
result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
EXPECT_EGL_TRUE(result && (count > 0));
return result;
}
};
class EGLBufferAgeTest_MSAA_DS : public EGLBufferAgeTest
{
public:
EGLBufferAgeTest_MSAA_DS() : EGLBufferAgeTest() {}
bool chooseConfig(EGLConfig *config) const override
{
bool result = false;
EGLint count = 0;
EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
EGLint attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
8,
EGL_DEPTH_SIZE,
8,
EGL_STENCIL_SIZE,
8,
EGL_RENDERABLE_TYPE,
clientVersion,
EGL_SAMPLE_BUFFERS,
1,
EGL_SAMPLES,
4,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_NONE};
result = eglChooseConfig(mDisplay, attribs, config, 1, &count);
EXPECT_EGL_TRUE(result && (count > 0));
return result;
}
};
// Query for buffer age
TEST_P(EGLBufferAgeTest, QueryBufferAge)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
const bool lockSurface3ExtSupported =
IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_lock_surface3");
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glClearColor(1.0, 0.0, 0.0, 1.0);
const uint32_t loopcount = 15;
EGLint expectedAge = 0;
for (uint32_t i = 0; i < loopcount; i++)
{
// Alternate between eglQuerySurface and eglQuerySurface64KHR
EGLint age = -1;
if (i % 2 == 0 || !lockSurface3ExtSupported)
{
age = queryAge(surface);
}
else
{
age = static_cast<EGLint>(queryAgeAttribKHR(surface));
}
// Should start with zero age and then flip to buffer count - which we don't know.
if ((expectedAge == 0) && (age > 0))
{
expectedAge = age;
}
EXPECT_EQ(age, expectedAge);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
EXPECT_GT(expectedAge, 0);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Query for buffer age after several loops of swapping buffers
TEST_P(EGLBufferAgeTest, QueryBufferAgeAfterLoop)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glClearColor(1.0, 0.0, 0.0, 1.0);
const uint32_t loopcount = 5;
for (uint32_t i = 0; i < loopcount; i++)
{
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
// This query age should not reset age
EXPECT_GT(queryAge(surface), 0);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Verify contents of buffer are as expected
TEST_P(EGLBufferAgeTest, VerifyContents)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
const angle::GLColor kLightGray(191, 191, 191, 255); // 0.75
const angle::GLColor kDarkGray(64, 64, 64, 255); // 0.25
const angle::GLColor kColorSet[] = {
GLColor::blue, GLColor::cyan, kDarkGray, GLColor::green, GLColor::red,
GLColor::white, GLColor::yellow, GLColor::black, GLColor::magenta, kLightGray,
GLColor::black, // Extra loops until color cycled through
GLColor::black, GLColor::black, GLColor::black, GLColor::black};
EGLint age = 0;
angle::GLColor expectedColor = GLColor::black;
int loopCount = (sizeof(kColorSet) / sizeof(kColorSet[0]));
for (int i = 0; i < loopCount; i++)
{
age = queryAge(surface);
if (age > 0)
{
// Check that color/content is what we expect
expectedColor = kColorSet[i - age];
EXPECT_PIXEL_COLOR_EQ(1, 1, expectedColor);
}
float red = kColorSet[i].R / 255.0;
float green = kColorSet[i].G / 255.0;
float blue = kColorSet[i].B / 255.0;
float alpha = kColorSet[i].A / 255.0;
glClearColor(red, green, blue, alpha);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
EXPECT_GT(age, 0);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Verify contents of buffer are as expected for a multisample image
TEST_P(EGLBufferAgeTest_MSAA, VerifyContentsForMultisampled)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest_MSAA", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
std::vector<angle::GLColor> kColorSet;
for (uint32_t i = 0; i < 16; i++)
{
kColorSet.emplace_back(i * 10, 0, 0, 255);
}
// Set up
glClearColor(0, 0, 0, 0);
glClearDepthf(0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
EGLint age = 0;
GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
GLint colorLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
for (size_t i = 0; i < kColorSet.size(); i++)
{
age = queryAge(surface);
if (age > 0)
{
// Check that color/content is what we expect
angle::GLColor expectedColor = kColorSet[i - age];
EXPECT_PIXEL_COLOR_EQ(1, 1, expectedColor);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(program);
glUniform4fv(colorLocation, 1, kColorSet[i].toNormalizedVector().data());
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
EXPECT_GE(age, 0);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Verify contents of buffer are as expected for a multisample image with depth/stencil enabled
TEST_P(EGLBufferAgeTest_MSAA_DS, VerifyContentsForMultisampledWithDepthStencil)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest_MSAA", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
std::vector<angle::GLColor> kColorSet;
for (uint32_t i = 0; i < 16; i++)
{
kColorSet.emplace_back(i * 10, 0, 0, 255);
}
// Set up
glClearColor(0, 0, 0, 0);
glClearDepthf(0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
EGLint age = 0;
GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
GLint colorLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
for (size_t i = 0; i < kColorSet.size(); i++)
{
age = queryAge(surface);
if (age > 0)
{
// Check that color/content is what we expect
angle::GLColor expectedColor = kColorSet[i - age];
EXPECT_PIXEL_COLOR_EQ(1, 1, expectedColor);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(program);
glUniform4fv(colorLocation, 1, kColorSet[i].toNormalizedVector().data());
drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
EXPECT_GE(age, 0);
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Verify EGL_BAD_SURFACE when not current
TEST_P(EGLBufferAgeTest, UncurrentContextBadSurface)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
EGLConfig config = EGL_NO_CONFIG_KHR;
EXPECT_TRUE(chooseConfig(&config));
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
// No current context
EGLint value = 0;
EXPECT_EGL_FALSE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &value));
EXPECT_EGL_ERROR(EGL_BAD_SURFACE);
EGLContext otherContext = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &otherContext));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
// Surface current to another context
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, otherContext));
// Make context the active context
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
value = 0;
EXPECT_EGL_FALSE(eglQuerySurface(mDisplay, surface, EGL_BUFFER_AGE_EXT, &value));
EXPECT_EGL_ERROR(EGL_BAD_SURFACE);
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, otherContext);
otherContext = EGL_NO_CONTEXT;
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Expect age always == 1 when EGL_BUFFER_PRESERVED is chosen
TEST_P(EGLBufferAgeTest, BufferPreserved)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
EGLConfig config = EGL_NO_CONFIG_KHR;
EGLint count = 0;
EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
EGLint attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
0,
EGL_RENDERABLE_TYPE,
clientVersion,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
EGL_NONE};
EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count));
// Skip if no configs, this indicates EGL_BUFFER_PRESERVED is not supported.
ANGLE_SKIP_TEST_IF(count == 0);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
glClearColor(1.0, 0.0, 0.0, 1.0);
const uint32_t loopcount = 10;
EGLint expectedAge = 1;
for (uint32_t i = 0; i < loopcount; i++)
{
EGLint age = queryAge(surface);
EXPECT_EQ(age, expectedAge);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
// Expect age always == 0 when EGL_SINGLE_BUFFER is chosen
TEST_P(EGLBufferAgeTest, SingleBuffer)
{
ANGLE_SKIP_TEST_IF(!mExtensionSupported);
ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_mutable_render_buffer"));
EGLConfig config = EGL_NO_CONFIG_KHR;
EGLint count = 0;
EGLint clientVersion = mMajorVersion == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT;
EGLint attribs[] = {EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_ALPHA_SIZE,
0,
EGL_RENDERABLE_TYPE,
clientVersion,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR,
EGL_NONE};
EXPECT_EGL_TRUE(eglChooseConfig(mDisplay, attribs, &config, 1, &count));
// Skip if no configs, this indicates EGL_SINGLE_BUFFER is not supported.
ANGLE_SKIP_TEST_IF(count == 0);
EGLContext context = EGL_NO_CONTEXT;
EXPECT_TRUE(createContext(config, &context));
ASSERT_EGL_SUCCESS() << "eglCreateContext failed.";
EGLSurface surface = EGL_NO_SURFACE;
OSWindow *osWindow = OSWindow::New();
osWindow->initialize("EGLBufferAgeTest", kWidth, kHeight);
EXPECT_TRUE(createWindowSurface(config, osWindow->getNativeWindow(), &surface));
ASSERT_EGL_SUCCESS() << "eglCreateWindowSurface failed.";
EXPECT_TRUE(eglMakeCurrent(mDisplay, surface, surface, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed.";
// Set render buffer to EGL_SINGLE_BUFFER
EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, surface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
glClearColor(1.0, 0.0, 0.0, 1.0);
// Expect age = 0 before first eglSwapBuffers() call
EGLint age = queryAge(surface);
EXPECT_EQ(age, 0);
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
const uint32_t loopcount = 10;
EGLint expectedAge = 0;
for (uint32_t i = 0; i < loopcount; i++)
{
age = queryAge(surface);
EXPECT_EQ(age, expectedAge);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR() << "glClear failed";
eglSwapBuffers(mDisplay, surface);
ASSERT_EGL_SUCCESS() << "eglSwapBuffers failed.";
}
EXPECT_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));
ASSERT_EGL_SUCCESS() << "eglMakeCurrent - uncurrent failed.";
eglDestroySurface(mDisplay, surface);
surface = EGL_NO_SURFACE;
osWindow->destroy();
OSWindow::Delete(&osWindow);
eglDestroyContext(mDisplay, context);
context = EGL_NO_CONTEXT;
}
ANGLE_INSTANTIATE_TEST(EGLBufferAgeTest,
WithNoFixture(ES2_METAL()),
WithNoFixture(ES3_METAL()),
WithNoFixture(ES2_OPENGLES()),
WithNoFixture(ES3_OPENGLES()),
WithNoFixture(ES2_OPENGL()),
WithNoFixture(ES3_OPENGL()),
WithNoFixture(ES2_VULKAN()),
WithNoFixture(ES3_VULKAN()));
ANGLE_INSTANTIATE_TEST(EGLBufferAgeTest_MSAA,
WithNoFixture(ES2_METAL()),
WithNoFixture(ES3_METAL()),
WithNoFixture(ES2_OPENGLES()),
WithNoFixture(ES3_OPENGLES()),
WithNoFixture(ES2_OPENGL()),
WithNoFixture(ES3_OPENGL()),
WithNoFixture(ES2_VULKAN()),
WithNoFixture(ES3_VULKAN()));
ANGLE_INSTANTIATE_TEST(EGLBufferAgeTest_MSAA_DS,
WithNoFixture(ES2_METAL()),
WithNoFixture(ES3_METAL()),
WithNoFixture(ES2_OPENGLES()),
WithNoFixture(ES3_OPENGLES()),
WithNoFixture(ES2_OPENGL()),
WithNoFixture(ES3_OPENGL()),
WithNoFixture(ES2_VULKAN()),
WithNoFixture(ES3_VULKAN()));