// // Copyright 2015 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. // // EGLSurfaceTest: // Tests pertaining to egl::Surface. // #include #include #include "common/Color.h" #include "common/platform.h" #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" #include "util/EGLWindow.h" #include "util/OSWindow.h" #include "util/Timer.h" #if defined(ANGLE_ENABLE_D3D11) # define INITGUID # include # include # include #endif using namespace angle; namespace { class EGLSurfaceTest : public ANGLETest { protected: EGLSurfaceTest() : mDisplay(EGL_NO_DISPLAY), mWindowSurface(EGL_NO_SURFACE), mPbufferSurface(EGL_NO_SURFACE), mContext(EGL_NO_CONTEXT), mSecondContext(EGL_NO_CONTEXT), mOSWindow(nullptr) {} void testSetUp() override { mOSWindow = OSWindow::New(); mOSWindow->initialize("EGLSurfaceTest", 64, 64); } void tearDownContextAndSurface() { if (mDisplay == EGL_NO_DISPLAY) { return; } eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (mWindowSurface != EGL_NO_SURFACE) { eglDestroySurface(mDisplay, mWindowSurface); mWindowSurface = EGL_NO_SURFACE; } if (mPbufferSurface != EGL_NO_SURFACE) { eglDestroySurface(mDisplay, mPbufferSurface); mPbufferSurface = EGL_NO_SURFACE; } if (mContext != EGL_NO_CONTEXT) { eglDestroyContext(mDisplay, mContext); mContext = EGL_NO_CONTEXT; } if (mSecondContext != EGL_NO_CONTEXT) { eglDestroyContext(mDisplay, mSecondContext); mSecondContext = EGL_NO_CONTEXT; } } // Release any resources created in the test body void testTearDown() override { tearDownContextAndSurface(); if (mDisplay != EGL_NO_DISPLAY) { eglTerminate(mDisplay); mDisplay = EGL_NO_DISPLAY; } mOSWindow->destroy(); OSWindow::Delete(&mOSWindow); ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE && mContext == EGL_NO_CONTEXT); } void initializeDisplay() { GLenum platformType = GetParam().getRenderer(); GLenum deviceType = GetParam().getDeviceType(); std::vector displayAttributes; displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); displayAttributes.push_back(platformType); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE); displayAttributes.push_back(EGL_DONT_CARE); displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE); displayAttributes.push_back(EGL_DONT_CARE); displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE); displayAttributes.push_back(deviceType); displayAttributes.push_back(EGL_NONE); mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast(mOSWindow->getNativeDisplay()), displayAttributes.data()); ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); EGLint majorVersion, minorVersion; ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE); eglBindAPI(EGL_OPENGL_ES_API); ASSERT_EGL_SUCCESS(); } void initializeSingleContext(EGLContext *context) { EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion, EGL_NONE}; *context = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes); ASSERT_EGL_SUCCESS(); } void initializeContext() { initializeSingleContext(&mContext); initializeSingleContext(&mSecondContext); } void initializeSurfaceWithAttribs(EGLConfig config, const std::vector &additionalAttributes) { mConfig = config; EGLint surfaceType = EGL_NONE; eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType); if (surfaceType & EGL_WINDOW_BIT) { std::vector windowAttributes = additionalAttributes; windowAttributes.push_back(EGL_NONE); // Create first window surface mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), windowAttributes.data()); ASSERT_EGL_SUCCESS(); } if (surfaceType & EGL_PBUFFER_BIT) { std::vector pbufferAttributes = additionalAttributes; // Give pbuffer non-zero dimensions. pbufferAttributes.push_back(EGL_WIDTH); pbufferAttributes.push_back(64); pbufferAttributes.push_back(EGL_HEIGHT); pbufferAttributes.push_back(64); pbufferAttributes.push_back(EGL_NONE); mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttributes.data()); ASSERT_EGL_SUCCESS(); } initializeContext(); } void initializeSurface(EGLConfig config) { std::vector additionalAttributes; initializeSurfaceWithAttribs(config, additionalAttributes); } EGLConfig chooseDefaultConfig(bool requireWindowSurface) const { const EGLint configAttributes[] = {EGL_RED_SIZE, EGL_DONT_CARE, EGL_GREEN_SIZE, EGL_DONT_CARE, EGL_BLUE_SIZE, EGL_DONT_CARE, EGL_ALPHA_SIZE, EGL_DONT_CARE, EGL_DEPTH_SIZE, EGL_DONT_CARE, EGL_STENCIL_SIZE, EGL_DONT_CARE, EGL_SAMPLE_BUFFERS, 0, EGL_SURFACE_TYPE, requireWindowSurface ? EGL_WINDOW_BIT : EGL_DONT_CARE, EGL_NONE}; EGLint configCount; EGLConfig config; if (eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) != EGL_TRUE) return nullptr; if (configCount != 1) return nullptr; return config; } void initializeSurfaceWithDefaultConfig(bool requireWindowSurface) { EGLConfig defaultConfig = chooseDefaultConfig(requireWindowSurface); ASSERT_NE(defaultConfig, nullptr); initializeSurface(defaultConfig); } GLuint createProgram() { return CompileProgram(angle::essl1_shaders::vs::Simple(), angle::essl1_shaders::fs::Red()); } void drawWithProgram(GLuint program) { glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib()); glUseProgram(program); const GLfloat vertices[] = { -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f, -1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f, }; glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionLocation); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); EXPECT_PIXEL_EQ(mOSWindow->getWidth() / 2, mOSWindow->getHeight() / 2, 255, 0, 0, 255); } void runMessageLoopTest(EGLSurface secondSurface, EGLContext secondContext) { eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); // Make a second context current eglMakeCurrent(mDisplay, secondSurface, secondSurface, secondContext); eglDestroySurface(mDisplay, mWindowSurface); // Create second window surface std::vector surfaceAttributes; surfaceAttributes.push_back(EGL_NONE); surfaceAttributes.push_back(EGL_NONE); mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), &surfaceAttributes[0]); ASSERT_EGL_SUCCESS(); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); mOSWindow->signalTestEvent(); mOSWindow->messageLoop(); ASSERT_TRUE(mOSWindow->didTestEventFire()); // Simple operation to test the FBO is set appropriately glClear(GL_COLOR_BUFFER_BIT); } EGLDisplay mDisplay; EGLSurface mWindowSurface; EGLSurface mPbufferSurface; EGLContext mContext; EGLContext mSecondContext; EGLConfig mConfig; OSWindow *mOSWindow; }; class EGLFloatSurfaceTest : public EGLSurfaceTest { protected: EGLFloatSurfaceTest() : EGLSurfaceTest() { setWindowWidth(512); setWindowHeight(512); } void testSetUp() override { mOSWindow = OSWindow::New(); mOSWindow->initialize("EGLFloatSurfaceTest", 64, 64); } void testTearDown() override { EGLSurfaceTest::testTearDown(); glDeleteProgram(mProgram); } GLuint createProgram() { constexpr char kFS[] = "precision highp float;\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0);\n" "}\n"; return CompileProgram(angle::essl1_shaders::vs::Simple(), kFS); } bool initializeSurfaceWithFloatConfig() { const EGLint configAttributes[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 16, EGL_GREEN_SIZE, 16, EGL_BLUE_SIZE, 16, EGL_ALPHA_SIZE, 16, EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT, EGL_NONE, EGL_NONE}; initializeDisplay(); EGLConfig config; if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE) { std::cout << "EGLConfig for a float surface is not supported, skipping test" << std::endl; return false; } initializeSurface(config); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); mProgram = createProgram(); return true; } GLuint mProgram; }; // Test clearing and checking the color is correct TEST_P(EGLFloatSurfaceTest, Clearing) { ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig()); ASSERT_NE(0u, mProgram) << "shader compilation failed."; ASSERT_GL_NO_ERROR(); GLColor32F clearColor(0.0f, 1.0f, 2.0f, 3.0f); glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A); glClear(GL_COLOR_BUFFER_BIT); ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR32F_EQ(0, 0, clearColor); } // Test drawing and checking the color is correct TEST_P(EGLFloatSurfaceTest, Drawing) { ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig()); ASSERT_NE(0u, mProgram) << "shader compilation failed."; ASSERT_GL_NO_ERROR(); glUseProgram(mProgram); drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f); EXPECT_PIXEL_32F_EQ(0, 0, 1.0f, 2.0f, 3.0f, 4.0f); } class EGLSurfaceTest3 : public EGLSurfaceTest {}; // Test a surface bug where we could have two Window surfaces active // at one time, blocking message loops. See http://crbug.com/475085 TEST_P(EGLSurfaceTest, MessageLoopBug) { // http://anglebug.com/3123 ANGLE_SKIP_TEST_IF(IsAndroid()); // http://anglebug.com/3138 ANGLE_SKIP_TEST_IF(IsOzone()); // http://anglebug.com/5485 ANGLE_SKIP_TEST_IF(IsIOS()); initializeDisplay(); initializeSurfaceWithDefaultConfig(true); runMessageLoopTest(EGL_NO_SURFACE, EGL_NO_CONTEXT); } // Tests the message loop bug, but with setting a second context // instead of null. TEST_P(EGLSurfaceTest, MessageLoopBugContext) { // http://anglebug.com/3123 ANGLE_SKIP_TEST_IF(IsAndroid()); // http://anglebug.com/3138 ANGLE_SKIP_TEST_IF(IsOzone()); // http://anglebug.com/5485 ANGLE_SKIP_TEST_IF(IsIOS()); initializeDisplay(); initializeSurfaceWithDefaultConfig(true); ANGLE_SKIP_TEST_IF(!mPbufferSurface); runMessageLoopTest(mPbufferSurface, mSecondContext); } // Test a bug where calling makeCurrent twice would release the surface TEST_P(EGLSurfaceTest, MakeCurrentTwice) { initializeDisplay(); initializeSurfaceWithDefaultConfig(false); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); // Simple operation to test the FBO is set appropriately glClear(GL_COLOR_BUFFER_BIT); } // Test that the window surface is correctly resized after calling swapBuffers TEST_P(EGLSurfaceTest, ResizeWindow) { // http://anglebug.com/4453 ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel()); // Flaky on Linux SwANGLE http://anglebug.com/4453 ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader()); // http://anglebug.com/5485 ANGLE_SKIP_TEST_IF(IsIOS()); ANGLE_SKIP_TEST_IF(IsLinux() && IsARM()); // Necessary for a window resizing test if there is no per-frame window size query setWindowVisible(mOSWindow, true); GLenum platform = GetParam().getRenderer(); bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE; int minSize = platformSupportsZeroSize ? 0 : 1; initializeDisplay(); initializeSurfaceWithDefaultConfig(true); initializeContext(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); EGLint height; eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); ASSERT_EGL_SUCCESS(); ASSERT_EQ(64, height); // initial size // set window's height to 0 (if possible) or 1 mOSWindow->resize(64, minSize); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); // TODO(syoussefi): the GLX implementation still reads the window size as 64x64 through // XGetGeometry. http://anglebug.com/3122 ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL()); eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); ASSERT_EGL_SUCCESS(); ASSERT_EQ(minSize, height); // restore window's height mOSWindow->resize(64, 64); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); ASSERT_EGL_SUCCESS(); ASSERT_EQ(64, height); } // Test that the backbuffer is correctly resized after calling swapBuffers TEST_P(EGLSurfaceTest, ResizeWindowWithDraw) { // http://anglebug.com/4453 ANGLE_SKIP_TEST_IF(IsLinux()); // http://anglebug.com/5485 ANGLE_SKIP_TEST_IF(IsIOS()); // Necessary for a window resizing test if there is no per-frame window size query setWindowVisible(mOSWindow, true); initializeDisplay(); initializeSurfaceWithDefaultConfig(true); initializeContext(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); int size = 64; EGLint height = 0; EGLint width = 0; eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); // Clear to red glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width); ASSERT_EGL_SUCCESS(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::red); EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::red); EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::red); EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack); // set window's size small size = 1; mOSWindow->resize(size, size); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); // Clear to green glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width); ASSERT_EGL_SUCCESS(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::green); EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack); // set window's height large size = 128; mOSWindow->resize(size, size); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); // Clear to blue glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height); eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width); ASSERT_EGL_SUCCESS(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::blue); EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::blue); EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::blue); EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack); } // Test that the window can be reset repeatedly before surface creation. TEST_P(EGLSurfaceTest, ResetNativeWindow) { setWindowVisible(mOSWindow, true); initializeDisplay(); for (int i = 0; i < 10; ++i) { mOSWindow->resetNativeWindow(); } initializeSurfaceWithDefaultConfig(true); initializeContext(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); eglSwapBuffers(mDisplay, mWindowSurface); ASSERT_EGL_SUCCESS(); } // Test creating a surface that supports a EGLConfig with 16bit // support GL_RGB565 TEST_P(EGLSurfaceTest, CreateWithEGLConfig5650Support) { const EGLint configAttributes[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; initializeDisplay(); EGLConfig config; if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE) { std::cout << "EGLConfig for a GL_RGB565 surface is not supported, skipping test" << std::endl; return; } initializeSurface(config); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); GLuint program = createProgram(); ASSERT_NE(0u, program); drawWithProgram(program); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); } // Test creating a surface that supports a EGLConfig with 16bit // support GL_RGBA4 TEST_P(EGLSurfaceTest, CreateWithEGLConfig4444Support) { const EGLint configAttributes[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 4, EGL_GREEN_SIZE, 4, EGL_BLUE_SIZE, 4, EGL_ALPHA_SIZE, 4, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; initializeDisplay(); EGLConfig config; if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE) { std::cout << "EGLConfig for a GL_RGBA4 surface is not supported, skipping test" << std::endl; return; } initializeSurface(config); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); GLuint program = createProgram(); ASSERT_NE(0u, program); drawWithProgram(program); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); } // Test creating a surface that supports a EGLConfig with 16bit // support GL_RGB5_A1 TEST_P(EGLSurfaceTest, CreateWithEGLConfig5551Support) { const EGLint configAttributes[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 5, EGL_BLUE_SIZE, 5, EGL_ALPHA_SIZE, 1, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; initializeDisplay(); EGLConfig config; if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE) { std::cout << "EGLConfig for a GL_RGB5_A1 surface is not supported, skipping test" << std::endl; return; } initializeSurface(config); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); GLuint program = createProgram(); ASSERT_NE(0u, program); drawWithProgram(program); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); } // Test creating a surface that supports a EGLConfig without alpha support TEST_P(EGLSurfaceTest, CreateWithEGLConfig8880Support) { const EGLint configAttributes[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; initializeDisplay(); EGLConfig config; if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE) { std::cout << "EGLConfig for a GL_RGB8_OES surface is not supported, skipping test" << std::endl; return; } initializeSurface(config); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); GLuint program = createProgram(); ASSERT_NE(0u, program); drawWithProgram(program); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); } TEST_P(EGLSurfaceTest, FixedSizeWindow) { const EGLint configAttributes[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; initializeDisplay(); ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE); ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_window_fixed_size")); constexpr EGLint kInitialSize = 64; constexpr EGLint kUpdateSize = 32; EGLint surfaceAttributes[] = { EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, kInitialSize, EGL_HEIGHT, kInitialSize, EGL_NONE, }; // Create first window surface mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), surfaceAttributes); ASSERT_EGL_SUCCESS(); ASSERT_NE(EGL_NO_SURFACE, mWindowSurface); initializeContext(); EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext)); ASSERT_EGL_SUCCESS(); EGLint queryIsFixedSize = 0; EXPECT_EGL_TRUE( eglQuerySurface(mDisplay, mWindowSurface, EGL_FIXED_SIZE_ANGLE, &queryIsFixedSize)); ASSERT_EGL_SUCCESS(); EXPECT_EGL_TRUE(queryIsFixedSize); EGLint queryWidth = 0; EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryWidth)); ASSERT_EGL_SUCCESS(); EXPECT_EQ(kInitialSize, queryWidth); EGLint queryHeight = 0; EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &queryHeight)); ASSERT_EGL_SUCCESS(); EXPECT_EQ(kInitialSize, queryHeight); // Update the size EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_WIDTH, kUpdateSize)); ASSERT_EGL_SUCCESS(); EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE)); ASSERT_EGL_SUCCESS(); EGLint queryUpdatedWidth = 0; EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryUpdatedWidth)); ASSERT_EGL_SUCCESS(); EXPECT_EQ(kUpdateSize, queryUpdatedWidth); } TEST_P(EGLSurfaceTest3, MakeCurrentDifferentSurfaces) { const EGLint configAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; EGLSurface firstPbufferSurface; EGLSurface secondPbufferSurface; initializeDisplay(); ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE); EGLint surfaceType = 0; eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType); bool supportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0; EGLint bindToTextureRGBA = 0; eglGetConfigAttrib(mDisplay, mConfig, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA); bool supportsBindTexImage = (bindToTextureRGBA == EGL_TRUE); const EGLint pBufferAttributes[] = { EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_TEXTURE_FORMAT, supportsPbuffers ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE, EGL_TEXTURE_TARGET, supportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE, EGL_NONE, EGL_NONE, }; // Create the surfaces firstPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes); ASSERT_EGL_SUCCESS(); ASSERT_NE(EGL_NO_SURFACE, firstPbufferSurface); secondPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes); ASSERT_EGL_SUCCESS(); ASSERT_NE(EGL_NO_SURFACE, secondPbufferSurface); initializeContext(); // Use the same surface for both draw and read EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext)); glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A); glClear(GL_COLOR_BUFFER_BIT); ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); // Use different surfaces for draw and read, read should stay the same EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, firstPbufferSurface, mContext)); glClearColor(GLColor::blue.R, GLColor::blue.G, GLColor::blue.B, GLColor::blue.A); glClear(GL_COLOR_BUFFER_BIT); ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); // Verify draw surface was cleared EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, secondPbufferSurface, mContext)); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, secondPbufferSurface, mContext)); ASSERT_EGL_SUCCESS(); // Blit the source surface to the destination surface glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST); ASSERT_GL_NO_ERROR(); EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext)); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue); } #if defined(ANGLE_ENABLE_D3D11) class EGLSurfaceTestD3D11 : public EGLSurfaceTest {}; // Test that rendering to an IDCompositionSurface using a pbuffer works. TEST_P(EGLSurfaceTestD3D11, CreateDirectCompositionSurface) { ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d")); initializeDisplay(); EGLAttrib device = 0; EGLAttrib newEglDevice = 0; ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice)); ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast(newEglDevice), EGL_D3D11_DEVICE_ANGLE, &device)); angle::ComPtr d3d11Device(reinterpret_cast(device)); ASSERT_TRUE(!!d3d11Device); HMODULE dcompLibrary = LoadLibraryA("dcomp.dll"); if (!dcompLibrary) { std::cout << "DirectComposition not supported" << std::endl; return; } typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE2)(IUnknown * dxgiDevice, REFIID iid, void **dcompositionDevice); PFN_DCOMPOSITION_CREATE_DEVICE2 createDComp = reinterpret_cast( GetProcAddress(dcompLibrary, "DCompositionCreateDevice2")); if (!createDComp) { std::cout << "DirectComposition2 not supported" << std::endl; FreeLibrary(dcompLibrary); return; } angle::ComPtr dcompDevice; HRESULT hr = createDComp(d3d11Device.Get(), IID_PPV_ARGS(dcompDevice.GetAddressOf())); ASSERT_TRUE(SUCCEEDED(hr)); angle::ComPtr dcompSurface; hr = dcompDevice->CreateSurface(100, 100, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ALPHA_MODE_PREMULTIPLIED, dcompSurface.GetAddressOf()); ASSERT_TRUE(SUCCEEDED(hr)); angle::ComPtr texture; POINT updateOffset; hr = dcompSurface->BeginDraw(nullptr, IID_PPV_ARGS(texture.GetAddressOf()), &updateOffset); ASSERT_TRUE(SUCCEEDED(hr)); const EGLint configAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; EGLConfig config; ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config)); const EGLint surfaceAttributes[] = {EGL_WIDTH, 100, EGL_HEIGHT, 100, EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, updateOffset.x, EGL_TEXTURE_OFFSET_Y_ANGLE, updateOffset.y, EGL_NONE}; EGLClientBuffer buffer = reinterpret_cast(texture.Get()); mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer, config, surfaceAttributes); ASSERT_EGL_SUCCESS(); mConfig = config; initializeContext(); eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext); ASSERT_EGL_SUCCESS(); GLuint program = createProgram(); ASSERT_NE(0u, program); drawWithProgram(program); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); } TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithTextureOffset) { ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d")); initializeDisplay(); const EGLint configAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE}; EGLConfig config; ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config)); mConfig = config; initializeContext(); EGLAttrib device = 0; EGLAttrib newEglDevice = 0; ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice)); ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast(newEglDevice), EGL_D3D11_DEVICE_ANGLE, &device)); angle::ComPtr d3d11Device(reinterpret_cast(device)); ASSERT_TRUE(!!d3d11Device); constexpr UINT kTextureWidth = 100; constexpr UINT kTextureHeight = 100; constexpr Color kOpaqueBlack(0, 0, 0, 255); std::vector> textureData(kTextureWidth * kTextureHeight, kOpaqueBlack); D3D11_SUBRESOURCE_DATA initialData = {}; initialData.pSysMem = textureData.data(); initialData.SysMemPitch = kTextureWidth * sizeof(kOpaqueBlack); D3D11_TEXTURE2D_DESC desc = {}; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.Width = kTextureWidth; desc.Height = kTextureHeight; desc.ArraySize = 1; desc.MipLevels = 1; desc.SampleDesc.Count = 1; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET; angle::ComPtr texture; HRESULT hr = d3d11Device->CreateTexture2D(&desc, &initialData, &texture); ASSERT_TRUE(SUCCEEDED(hr)); angle::ComPtr d3d11Context; d3d11Device->GetImmediateContext(&d3d11Context); // Specify a texture offset of (50, 50) when rendering to the pbuffer surface. const EGLint surfaceAttributes[] = {EGL_WIDTH, kTextureWidth, EGL_HEIGHT, kTextureHeight, EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, 50, EGL_TEXTURE_OFFSET_Y_ANGLE, 50, EGL_NONE}; EGLClientBuffer buffer = reinterpret_cast(texture.Get()); mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer, config, surfaceAttributes); ASSERT_EGL_SUCCESS(); eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext); ASSERT_EGL_SUCCESS(); // glClear should only clear subrect at offset (50, 50) without explicit scissor. glClearColor(0, 0, 1, 1); // Blue glClear(GL_COLOR_BUFFER_BIT); EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255); EXPECT_PIXEL_EQ(75, 75, 0, 0, 255, 255); EXPECT_GL_NO_ERROR(); // Drawing with a shader should also update the same subrect only without explicit viewport. GLuint program = createProgram(); // Red ASSERT_NE(0u, program); GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib()); glUseProgram(program); const GLfloat vertices[] = { -1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f, -1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f, }; glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionLocation); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255); EXPECT_PIXEL_EQ(75, 75, 255, 0, 0, 255); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); EXPECT_GL_NO_ERROR(); // Blit framebuffer should also blit to the same subrect despite the dstX/Y arguments. GLRenderbuffer renderBuffer; glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 50, 50); EXPECT_GL_NO_ERROR(); GLFramebuffer framebuffer; glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer); EXPECT_GL_NO_ERROR(); glClearColor(0, 1, 0, 1); // Green glClear(GL_COLOR_BUFFER_BIT); EXPECT_PIXEL_EQ(25, 25, 0, 255, 0, 255); EXPECT_GL_NO_ERROR(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0u); glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer); glBlitFramebuffer(0, 0, 50, 50, 0, 0, 50, 50, GL_COLOR_BUFFER_BIT, GL_NEAREST); EXPECT_GL_NO_ERROR(); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0u); EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255); EXPECT_PIXEL_EQ(75, 75, 0, 255, 0, 255); EXPECT_GL_NO_ERROR(); } TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithMSAA) { ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d")); // clang-format off const EGLint configAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES, 4, EGL_NONE }; // clang-format on initializeDisplay(); EGLConfig config; if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE) { std::cout << "EGLConfig for 4xMSAA is not supported, skipping test" << std::endl; return; } initializeSurface(config); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); GLuint program = createProgram(); ASSERT_NE(0u, program); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib()); ASSERT_NE(-1, positionLocation); glUseProgram(program); const GLfloat halfPixelOffset = 0.5f * 2.0f / mOSWindow->getWidth(); // clang-format off const GLfloat vertices[] = { -1.0f + halfPixelOffset, 1.0f, 0.5f, -1.0f + halfPixelOffset, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f }; // clang-format on glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionLocation); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(positionLocation); glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); EXPECT_PIXEL_NEAR(0, 0, 127, 0, 0, 255, 10); EXPECT_GL_NO_ERROR(); glDeleteProgram(program); } #endif // ANGLE_ENABLE_D3D11 // Verify switching between a surface with robust resource init and one without still clears alpha. TEST_P(EGLSurfaceTest, RobustResourceInitAndEmulatedAlpha) { // http://anglebug.com/5279 ANGLE_SKIP_TEST_IF(IsNVIDIA() && isGLRenderer() && IsLinux()); // http://anglebug.com/5280 ANGLE_SKIP_TEST_IF(IsAndroid() && IsNexus5X() && isGLESRenderer()); initializeDisplay(); ASSERT_NE(mDisplay, EGL_NO_DISPLAY); ANGLE_SKIP_TEST_IF( !IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_robust_resource_initialization")); // Initialize and draw red to a Surface with robust resource init enabled. constexpr EGLint kRGBAAttributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE}; EGLint configCount = 0; EGLConfig rgbaConfig = nullptr; ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAAttributes, &rgbaConfig, 1, &configCount)); ASSERT_EQ(configCount, 1); ASSERT_NE(rgbaConfig, nullptr); std::vector robustInitAttribs; robustInitAttribs.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE); robustInitAttribs.push_back(EGL_TRUE); initializeSurfaceWithAttribs(rgbaConfig, robustInitAttribs); ASSERT_EGL_SUCCESS(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); initializeSingleContext(&mContext); ASSERT_EGL_SUCCESS(); ASSERT_NE(mContext, EGL_NO_CONTEXT); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); eglSwapBuffers(mDisplay, mWindowSurface); // RGBA robust init setup complete. Draw red and verify. { ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); glUseProgram(program); drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); eglSwapBuffers(mDisplay, mWindowSurface); } tearDownContextAndSurface(); // Create second RGB surface with robust resource disabled. constexpr EGLint kRGBAttributes[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE}; configCount = 0; EGLConfig rgbConfig = nullptr; ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAttributes, &rgbConfig, 1, &configCount)); ASSERT_EQ(configCount, 1); ASSERT_NE(rgbConfig, nullptr); initializeSurface(rgbConfig); ASSERT_EGL_SUCCESS(); ASSERT_NE(mWindowSurface, EGL_NO_SURFACE); initializeSingleContext(&mContext); ASSERT_EGL_SUCCESS(); ASSERT_NE(mContext, EGL_NO_CONTEXT); eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); ASSERT_EGL_SUCCESS(); // RGB non-robust init setup complete. Draw red and verify. { ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red()); glUseProgram(program); drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f); ASSERT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red); eglSwapBuffers(mDisplay, mWindowSurface); } } } // anonymous namespace ANGLE_INSTANTIATE_TEST(EGLSurfaceTest, WithNoFixture(ES2_D3D9()), WithNoFixture(ES2_D3D11()), WithNoFixture(ES3_D3D11()), WithNoFixture(ES2_OPENGL()), WithNoFixture(ES3_OPENGL()), WithNoFixture(ES2_OPENGLES()), WithNoFixture(ES3_OPENGLES()), WithNoFixture(ES2_VULKAN()), WithNoFixture(ES3_VULKAN()), WithNoFixture(ES2_VULKAN_SWIFTSHADER()), WithNoFixture(ES3_VULKAN_SWIFTSHADER())); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLFloatSurfaceTest); ANGLE_INSTANTIATE_TEST(EGLFloatSurfaceTest, WithNoFixture(ES2_OPENGL()), WithNoFixture(ES3_OPENGL()), WithNoFixture(ES2_VULKAN()), WithNoFixture(ES3_VULKAN())); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSurfaceTest3); ANGLE_INSTANTIATE_TEST(EGLSurfaceTest3, WithNoFixture(ES3_VULKAN())); #if defined(ANGLE_ENABLE_D3D11) ANGLE_INSTANTIATE_TEST(EGLSurfaceTestD3D11, WithNoFixture(ES2_D3D11()), WithNoFixture(ES3_D3D11())); #endif