Path: blob/main_old/src/tests/egl_tests/EGLSurfaceTest.cpp
1693 views
//1// Copyright 2015 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// EGLSurfaceTest:6// Tests pertaining to egl::Surface.7//89#include <gtest/gtest.h>1011#include <vector>1213#include "common/Color.h"14#include "common/platform.h"15#include "test_utils/ANGLETest.h"16#include "test_utils/gl_raii.h"17#include "util/EGLWindow.h"18#include "util/OSWindow.h"19#include "util/Timer.h"2021#if defined(ANGLE_ENABLE_D3D11)22# define INITGUID23# include <guiddef.h>2425# include <d3d11.h>26# include <dcomp.h>27#endif2829using namespace angle;3031namespace32{3334class EGLSurfaceTest : public ANGLETest35{36protected:37EGLSurfaceTest()38: mDisplay(EGL_NO_DISPLAY),39mWindowSurface(EGL_NO_SURFACE),40mPbufferSurface(EGL_NO_SURFACE),41mContext(EGL_NO_CONTEXT),42mSecondContext(EGL_NO_CONTEXT),43mOSWindow(nullptr)44{}4546void testSetUp() override47{48mOSWindow = OSWindow::New();49mOSWindow->initialize("EGLSurfaceTest", 64, 64);50}5152void tearDownContextAndSurface()53{54if (mDisplay == EGL_NO_DISPLAY)55{56return;57}5859eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);6061if (mWindowSurface != EGL_NO_SURFACE)62{63eglDestroySurface(mDisplay, mWindowSurface);64mWindowSurface = EGL_NO_SURFACE;65}6667if (mPbufferSurface != EGL_NO_SURFACE)68{69eglDestroySurface(mDisplay, mPbufferSurface);70mPbufferSurface = EGL_NO_SURFACE;71}7273if (mContext != EGL_NO_CONTEXT)74{75eglDestroyContext(mDisplay, mContext);76mContext = EGL_NO_CONTEXT;77}7879if (mSecondContext != EGL_NO_CONTEXT)80{81eglDestroyContext(mDisplay, mSecondContext);82mSecondContext = EGL_NO_CONTEXT;83}84}8586// Release any resources created in the test body87void testTearDown() override88{89tearDownContextAndSurface();9091if (mDisplay != EGL_NO_DISPLAY)92{93eglTerminate(mDisplay);94mDisplay = EGL_NO_DISPLAY;95}9697mOSWindow->destroy();98OSWindow::Delete(&mOSWindow);99100ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE && mContext == EGL_NO_CONTEXT);101}102103void initializeDisplay()104{105GLenum platformType = GetParam().getRenderer();106GLenum deviceType = GetParam().getDeviceType();107108std::vector<EGLint> displayAttributes;109displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);110displayAttributes.push_back(platformType);111displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);112displayAttributes.push_back(EGL_DONT_CARE);113displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);114displayAttributes.push_back(EGL_DONT_CARE);115displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);116displayAttributes.push_back(deviceType);117displayAttributes.push_back(EGL_NONE);118119mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,120reinterpret_cast<void *>(mOSWindow->getNativeDisplay()),121displayAttributes.data());122ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);123124EGLint majorVersion, minorVersion;125ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE);126127eglBindAPI(EGL_OPENGL_ES_API);128ASSERT_EGL_SUCCESS();129}130131void initializeSingleContext(EGLContext *context)132{133EGLint contextAttibutes[] = {EGL_CONTEXT_CLIENT_VERSION, GetParam().majorVersion, EGL_NONE};134135*context = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes);136ASSERT_EGL_SUCCESS();137}138139void initializeContext()140{141// Only initialize the contexts once.142if (mContext == EGL_NO_CONTEXT)143{144initializeSingleContext(&mContext);145}146if (mSecondContext == EGL_NO_CONTEXT)147{148initializeSingleContext(&mSecondContext);149}150}151152void initializeWindowSurfaceWithAttribs(EGLConfig config,153const std::vector<EGLint> &additionalAttributes,154EGLenum expectedResult)155{156ASSERT_EQ(mWindowSurface, EGL_NO_SURFACE);157158EGLint surfaceType = EGL_NONE;159eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);160161if (surfaceType & EGL_WINDOW_BIT)162{163std::vector<EGLint> windowAttributes = additionalAttributes;164windowAttributes.push_back(EGL_NONE);165166// Create first window surface167mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),168windowAttributes.data());169}170171ASSERT_EGLENUM_EQ(eglGetError(), expectedResult);172}173174void initializeSurfaceWithAttribs(EGLConfig config,175const std::vector<EGLint> &additionalAttributes)176{177mConfig = config;178179EGLint surfaceType = EGL_NONE;180eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);181182if (surfaceType & EGL_WINDOW_BIT)183{184initializeWindowSurfaceWithAttribs(config, additionalAttributes, EGL_SUCCESS);185}186187if (surfaceType & EGL_PBUFFER_BIT)188{189std::vector<EGLint> pbufferAttributes = additionalAttributes;190191// Give pbuffer non-zero dimensions.192pbufferAttributes.push_back(EGL_WIDTH);193pbufferAttributes.push_back(64);194pbufferAttributes.push_back(EGL_HEIGHT);195pbufferAttributes.push_back(64);196pbufferAttributes.push_back(EGL_NONE);197198mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttributes.data());199ASSERT_EGL_SUCCESS();200}201202initializeContext();203}204205void initializeSurface(EGLConfig config)206{207std::vector<EGLint> additionalAttributes;208initializeSurfaceWithAttribs(config, additionalAttributes);209}210211EGLConfig chooseDefaultConfig(bool requireWindowSurface) const212{213const EGLint configAttributes[] = {EGL_RED_SIZE,214EGL_DONT_CARE,215EGL_GREEN_SIZE,216EGL_DONT_CARE,217EGL_BLUE_SIZE,218EGL_DONT_CARE,219EGL_ALPHA_SIZE,220EGL_DONT_CARE,221EGL_DEPTH_SIZE,222EGL_DONT_CARE,223EGL_STENCIL_SIZE,224EGL_DONT_CARE,225EGL_SAMPLE_BUFFERS,2260,227EGL_SURFACE_TYPE,228requireWindowSurface ? EGL_WINDOW_BIT : EGL_DONT_CARE,229EGL_NONE};230231EGLint configCount;232EGLConfig config;233if (eglChooseConfig(mDisplay, configAttributes, &config, 1, &configCount) != EGL_TRUE)234return nullptr;235if (configCount != 1)236return nullptr;237return config;238}239240void initializeSurfaceWithDefaultConfig(bool requireWindowSurface)241{242EGLConfig defaultConfig = chooseDefaultConfig(requireWindowSurface);243ASSERT_NE(defaultConfig, nullptr);244initializeSurface(defaultConfig);245}246247GLuint createProgram()248{249return CompileProgram(angle::essl1_shaders::vs::Simple(), angle::essl1_shaders::fs::Red());250}251252void drawWithProgram(GLuint program)253{254glClearColor(0, 0, 0, 1);255glClear(GL_COLOR_BUFFER_BIT);256257GLint positionLocation =258glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());259260glUseProgram(program);261262const GLfloat vertices[] = {263-1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,264265-1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f,266};267268glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);269glEnableVertexAttribArray(positionLocation);270271glDrawArrays(GL_TRIANGLES, 0, 6);272273glDisableVertexAttribArray(positionLocation);274glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);275276EXPECT_PIXEL_EQ(mOSWindow->getWidth() / 2, mOSWindow->getHeight() / 2, 255, 0, 0, 255);277}278279void runMessageLoopTest(EGLSurface secondSurface, EGLContext secondContext)280{281eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);282ASSERT_EGL_SUCCESS();283284// Make a second context current285eglMakeCurrent(mDisplay, secondSurface, secondSurface, secondContext);286eglDestroySurface(mDisplay, mWindowSurface);287288// Create second window surface289std::vector<EGLint> surfaceAttributes;290surfaceAttributes.push_back(EGL_NONE);291surfaceAttributes.push_back(EGL_NONE);292293mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(),294&surfaceAttributes[0]);295ASSERT_EGL_SUCCESS();296297eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);298ASSERT_EGL_SUCCESS();299300mOSWindow->signalTestEvent();301mOSWindow->messageLoop();302ASSERT_TRUE(mOSWindow->didTestEventFire());303304// Simple operation to test the FBO is set appropriately305glClear(GL_COLOR_BUFFER_BIT);306}307308void drawQuadThenTearDown();309310EGLDisplay mDisplay;311EGLSurface mWindowSurface;312EGLSurface mPbufferSurface;313EGLContext mContext;314EGLContext mSecondContext;315EGLConfig mConfig;316OSWindow *mOSWindow;317};318319class EGLFloatSurfaceTest : public EGLSurfaceTest320{321protected:322EGLFloatSurfaceTest() : EGLSurfaceTest()323{324setWindowWidth(512);325setWindowHeight(512);326}327328void testSetUp() override329{330mOSWindow = OSWindow::New();331mOSWindow->initialize("EGLFloatSurfaceTest", 64, 64);332}333334void testTearDown() override335{336EGLSurfaceTest::testTearDown();337glDeleteProgram(mProgram);338}339340GLuint createProgram()341{342constexpr char kFS[] =343"precision highp float;\n"344"void main()\n"345"{\n"346" gl_FragColor = vec4(1.0, 2.0, 3.0, 4.0);\n"347"}\n";348return CompileProgram(angle::essl1_shaders::vs::Simple(), kFS);349}350351bool initializeSurfaceWithFloatConfig()352{353const EGLint configAttributes[] = {EGL_SURFACE_TYPE,354EGL_WINDOW_BIT,355EGL_RED_SIZE,35616,357EGL_GREEN_SIZE,35816,359EGL_BLUE_SIZE,36016,361EGL_ALPHA_SIZE,36216,363EGL_COLOR_COMPONENT_TYPE_EXT,364EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,365EGL_NONE,366EGL_NONE};367368initializeDisplay();369EGLConfig config;370if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)371{372std::cout << "EGLConfig for a float surface is not supported, skipping test"373<< std::endl;374return false;375}376377initializeSurface(config);378379eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);380mProgram = createProgram();381return true;382}383384GLuint mProgram;385};386387// Test clearing and checking the color is correct388TEST_P(EGLFloatSurfaceTest, Clearing)389{390ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig());391392ASSERT_NE(0u, mProgram) << "shader compilation failed.";393ASSERT_GL_NO_ERROR();394395GLColor32F clearColor(0.0f, 1.0f, 2.0f, 3.0f);396glClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A);397glClear(GL_COLOR_BUFFER_BIT);398ASSERT_GL_NO_ERROR();399400EXPECT_PIXEL_COLOR32F_EQ(0, 0, clearColor);401}402403// Test drawing and checking the color is correct404TEST_P(EGLFloatSurfaceTest, Drawing)405{406ANGLE_SKIP_TEST_IF(!initializeSurfaceWithFloatConfig());407408ASSERT_NE(0u, mProgram) << "shader compilation failed.";409ASSERT_GL_NO_ERROR();410411glUseProgram(mProgram);412drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);413414EXPECT_PIXEL_32F_EQ(0, 0, 1.0f, 2.0f, 3.0f, 4.0f);415}416417class EGLSurfaceTest3 : public EGLSurfaceTest418{};419420// Test a surface bug where we could have two Window surfaces active421// at one time, blocking message loops. See http://crbug.com/475085422TEST_P(EGLSurfaceTest, MessageLoopBug)423{424// http://anglebug.com/3123425ANGLE_SKIP_TEST_IF(IsAndroid());426427// http://anglebug.com/3138428ANGLE_SKIP_TEST_IF(IsOzone());429430// http://anglebug.com/5485431ANGLE_SKIP_TEST_IF(IsIOS());432433initializeDisplay();434initializeSurfaceWithDefaultConfig(true);435436runMessageLoopTest(EGL_NO_SURFACE, EGL_NO_CONTEXT);437}438439// Tests the message loop bug, but with setting a second context440// instead of null.441TEST_P(EGLSurfaceTest, MessageLoopBugContext)442{443// http://anglebug.com/3123444ANGLE_SKIP_TEST_IF(IsAndroid());445446// http://anglebug.com/3138447ANGLE_SKIP_TEST_IF(IsOzone());448449// http://anglebug.com/5485450ANGLE_SKIP_TEST_IF(IsIOS());451452initializeDisplay();453initializeSurfaceWithDefaultConfig(true);454455ANGLE_SKIP_TEST_IF(!mPbufferSurface);456runMessageLoopTest(mPbufferSurface, mSecondContext);457}458459// Test a bug where calling makeCurrent twice would release the surface460TEST_P(EGLSurfaceTest, MakeCurrentTwice)461{462initializeDisplay();463initializeSurfaceWithDefaultConfig(false);464465eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);466ASSERT_EGL_SUCCESS();467468eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);469ASSERT_EGL_SUCCESS();470471// Simple operation to test the FBO is set appropriately472glClear(GL_COLOR_BUFFER_BIT);473}474475// Test that the window surface is correctly resized after calling swapBuffers476TEST_P(EGLSurfaceTest, ResizeWindow)477{478// http://anglebug.com/4453479ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel());480// Flaky on Linux SwANGLE http://anglebug.com/4453481ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());482// http://anglebug.com/5485483ANGLE_SKIP_TEST_IF(IsIOS());484ANGLE_SKIP_TEST_IF(IsLinux() && IsARM());485486// Necessary for a window resizing test if there is no per-frame window size query487setWindowVisible(mOSWindow, true);488489GLenum platform = GetParam().getRenderer();490bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||491platform == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;492int minSize = platformSupportsZeroSize ? 0 : 1;493494initializeDisplay();495initializeSurfaceWithDefaultConfig(true);496ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);497498eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);499eglSwapBuffers(mDisplay, mWindowSurface);500ASSERT_EGL_SUCCESS();501502EGLint height;503eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);504ASSERT_EGL_SUCCESS();505ASSERT_EQ(64, height); // initial size506507// set window's height to 0 (if possible) or 1508mOSWindow->resize(64, minSize);509510eglSwapBuffers(mDisplay, mWindowSurface);511ASSERT_EGL_SUCCESS();512513// TODO(syoussefi): the GLX implementation still reads the window size as 64x64 through514// XGetGeometry. http://anglebug.com/3122515ANGLE_SKIP_TEST_IF(IsLinux() && IsOpenGL());516517eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);518ASSERT_EGL_SUCCESS();519ASSERT_EQ(minSize, height);520521// restore window's height522mOSWindow->resize(64, 64);523524eglSwapBuffers(mDisplay, mWindowSurface);525ASSERT_EGL_SUCCESS();526527eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);528ASSERT_EGL_SUCCESS();529ASSERT_EQ(64, height);530}531532// Test that the backbuffer is correctly resized after calling swapBuffers533TEST_P(EGLSurfaceTest, ResizeWindowWithDraw)534{535// http://anglebug.com/4453536ANGLE_SKIP_TEST_IF(IsLinux());537// http://anglebug.com/5485538ANGLE_SKIP_TEST_IF(IsIOS());539540// Necessary for a window resizing test if there is no per-frame window size query541setWindowVisible(mOSWindow, true);542543initializeDisplay();544initializeSurfaceWithDefaultConfig(true);545initializeContext();546ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);547548int size = 64;549EGLint height = 0;550EGLint width = 0;551552eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);553eglSwapBuffers(mDisplay, mWindowSurface);554ASSERT_EGL_SUCCESS();555556// Clear to red557glClearColor(1.0f, 0.0f, 0.0f, 1.0f);558glClear(GL_COLOR_BUFFER_BIT);559560eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);561eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);562ASSERT_EGL_SUCCESS();563564EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);565EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::red);566EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::red);567EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::red);568EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);569EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);570EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);571EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);572573// set window's size small574size = 1;575mOSWindow->resize(size, size);576577eglSwapBuffers(mDisplay, mWindowSurface);578ASSERT_EGL_SUCCESS();579580// Clear to green581glClearColor(0.0f, 1.0f, 0.0f, 1.0f);582glClear(GL_COLOR_BUFFER_BIT);583584eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);585eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);586ASSERT_EGL_SUCCESS();587588EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);589EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::green);590EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::green);591EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::green);592EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);593EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);594EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);595EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);596597// set window's height large598size = 128;599mOSWindow->resize(size, size);600601eglSwapBuffers(mDisplay, mWindowSurface);602ASSERT_EGL_SUCCESS();603604// Clear to blue605glClearColor(0.0f, 0.0f, 1.0f, 1.0f);606glClear(GL_COLOR_BUFFER_BIT);607608eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &height);609eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &width);610ASSERT_EGL_SUCCESS();611612EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);613EXPECT_PIXEL_COLOR_EQ(size - 1, 0, GLColor::blue);614EXPECT_PIXEL_COLOR_EQ(size - 1, size - 1, GLColor::blue);615EXPECT_PIXEL_COLOR_EQ(0, size - 1, GLColor::blue);616EXPECT_PIXEL_COLOR_EQ(-1, -1, GLColor::transparentBlack);617EXPECT_PIXEL_COLOR_EQ(size, 0, GLColor::transparentBlack);618EXPECT_PIXEL_COLOR_EQ(0, size, GLColor::transparentBlack);619EXPECT_PIXEL_COLOR_EQ(size, size, GLColor::transparentBlack);620}621622// Test that the window can be reset repeatedly before surface creation.623TEST_P(EGLSurfaceTest, ResetNativeWindow)624{625setWindowVisible(mOSWindow, true);626627initializeDisplay();628629for (int i = 0; i < 10; ++i)630{631mOSWindow->resetNativeWindow();632}633634initializeSurfaceWithDefaultConfig(true);635initializeContext();636ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);637638eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);639640eglSwapBuffers(mDisplay, mWindowSurface);641ASSERT_EGL_SUCCESS();642}643644// Test creating a surface that supports a EGLConfig with 16bit645// support GL_RGB565646TEST_P(EGLSurfaceTest, CreateWithEGLConfig5650Support)647{648const EGLint configAttributes[] = {EGL_SURFACE_TYPE,649EGL_WINDOW_BIT,650EGL_RED_SIZE,6515,652EGL_GREEN_SIZE,6536,654EGL_BLUE_SIZE,6555,656EGL_ALPHA_SIZE,6570,658EGL_DEPTH_SIZE,6590,660EGL_STENCIL_SIZE,6610,662EGL_SAMPLE_BUFFERS,6630,664EGL_NONE};665666initializeDisplay();667EGLConfig config;668if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)669{670std::cout << "EGLConfig for a GL_RGB565 surface is not supported, skipping test"671<< std::endl;672return;673}674675initializeSurface(config);676677eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);678ASSERT_EGL_SUCCESS();679680GLuint program = createProgram();681ASSERT_NE(0u, program);682drawWithProgram(program);683EXPECT_GL_NO_ERROR();684glDeleteProgram(program);685}686687// Test creating a surface that supports a EGLConfig with 16bit688// support GL_RGBA4689TEST_P(EGLSurfaceTest, CreateWithEGLConfig4444Support)690{691const EGLint configAttributes[] = {EGL_SURFACE_TYPE,692EGL_WINDOW_BIT,693EGL_RED_SIZE,6944,695EGL_GREEN_SIZE,6964,697EGL_BLUE_SIZE,6984,699EGL_ALPHA_SIZE,7004,701EGL_DEPTH_SIZE,7020,703EGL_STENCIL_SIZE,7040,705EGL_SAMPLE_BUFFERS,7060,707EGL_NONE};708709initializeDisplay();710EGLConfig config;711if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)712{713std::cout << "EGLConfig for a GL_RGBA4 surface is not supported, skipping test"714<< std::endl;715return;716}717718initializeSurface(config);719720eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);721ASSERT_EGL_SUCCESS();722723GLuint program = createProgram();724ASSERT_NE(0u, program);725drawWithProgram(program);726EXPECT_GL_NO_ERROR();727glDeleteProgram(program);728}729730// Test creating a surface that supports a EGLConfig with 16bit731// support GL_RGB5_A1732TEST_P(EGLSurfaceTest, CreateWithEGLConfig5551Support)733{734const EGLint configAttributes[] = {EGL_SURFACE_TYPE,735EGL_WINDOW_BIT,736EGL_RED_SIZE,7375,738EGL_GREEN_SIZE,7395,740EGL_BLUE_SIZE,7415,742EGL_ALPHA_SIZE,7431,744EGL_DEPTH_SIZE,7450,746EGL_STENCIL_SIZE,7470,748EGL_SAMPLE_BUFFERS,7490,750EGL_NONE};751752initializeDisplay();753EGLConfig config;754if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)755{756std::cout << "EGLConfig for a GL_RGB5_A1 surface is not supported, skipping test"757<< std::endl;758return;759}760761initializeSurface(config);762763eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);764ASSERT_EGL_SUCCESS();765766GLuint program = createProgram();767ASSERT_NE(0u, program);768drawWithProgram(program);769EXPECT_GL_NO_ERROR();770glDeleteProgram(program);771}772773// Test creating a surface that supports a EGLConfig without alpha support774TEST_P(EGLSurfaceTest, CreateWithEGLConfig8880Support)775{776const EGLint configAttributes[] = {EGL_SURFACE_TYPE,777EGL_WINDOW_BIT,778EGL_RED_SIZE,7798,780EGL_GREEN_SIZE,7818,782EGL_BLUE_SIZE,7838,784EGL_ALPHA_SIZE,7850,786EGL_DEPTH_SIZE,7870,788EGL_STENCIL_SIZE,7890,790EGL_SAMPLE_BUFFERS,7910,792EGL_NONE};793794initializeDisplay();795EGLConfig config;796if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)797{798std::cout << "EGLConfig for a GL_RGB8_OES surface is not supported, skipping test"799<< std::endl;800return;801}802803initializeSurface(config);804805eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);806ASSERT_EGL_SUCCESS();807808GLuint program = createProgram();809ASSERT_NE(0u, program);810drawWithProgram(program);811EXPECT_GL_NO_ERROR();812glDeleteProgram(program);813}814815TEST_P(EGLSurfaceTest, FixedSizeWindow)816{817const EGLint configAttributes[] = {EGL_SURFACE_TYPE,818EGL_WINDOW_BIT,819EGL_RED_SIZE,8208,821EGL_GREEN_SIZE,8228,823EGL_BLUE_SIZE,8248,825EGL_ALPHA_SIZE,8260,827EGL_DEPTH_SIZE,8280,829EGL_STENCIL_SIZE,8300,831EGL_SAMPLE_BUFFERS,8320,833EGL_NONE};834835initializeDisplay();836ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);837838ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_window_fixed_size"));839840constexpr EGLint kInitialSize = 64;841constexpr EGLint kUpdateSize = 32;842843EGLint surfaceAttributes[] = {844EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, kInitialSize, EGL_HEIGHT, kInitialSize, EGL_NONE,845};846847// Create first window surface848mWindowSurface =849eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), surfaceAttributes);850ASSERT_EGL_SUCCESS();851ASSERT_NE(EGL_NO_SURFACE, mWindowSurface);852853initializeContext();854EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));855ASSERT_EGL_SUCCESS();856857EGLint queryIsFixedSize = 0;858EXPECT_EGL_TRUE(859eglQuerySurface(mDisplay, mWindowSurface, EGL_FIXED_SIZE_ANGLE, &queryIsFixedSize));860ASSERT_EGL_SUCCESS();861EXPECT_EGL_TRUE(queryIsFixedSize);862863EGLint queryWidth = 0;864EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryWidth));865ASSERT_EGL_SUCCESS();866EXPECT_EQ(kInitialSize, queryWidth);867868EGLint queryHeight = 0;869EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &queryHeight));870ASSERT_EGL_SUCCESS();871EXPECT_EQ(kInitialSize, queryHeight);872873// Update the size874EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_WIDTH, kUpdateSize));875ASSERT_EGL_SUCCESS();876877EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));878ASSERT_EGL_SUCCESS();879880EGLint queryUpdatedWidth = 0;881EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryUpdatedWidth));882ASSERT_EGL_SUCCESS();883EXPECT_EQ(kUpdateSize, queryUpdatedWidth);884}885886TEST_P(EGLSurfaceTest3, MakeCurrentDifferentSurfaces)887{888const EGLint configAttributes[] = {889EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,890EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};891EGLSurface firstPbufferSurface;892EGLSurface secondPbufferSurface;893894initializeDisplay();895ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);896897EGLint surfaceType = 0;898eglGetConfigAttrib(mDisplay, mConfig, EGL_SURFACE_TYPE, &surfaceType);899bool supportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;900EGLint bindToTextureRGBA = 0;901eglGetConfigAttrib(mDisplay, mConfig, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);902bool supportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);903904const EGLint pBufferAttributes[] = {905EGL_WIDTH, 64,906EGL_HEIGHT, 64,907EGL_TEXTURE_FORMAT, supportsPbuffers ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,908EGL_TEXTURE_TARGET, supportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,909EGL_NONE, EGL_NONE,910};911912// Create the surfaces913firstPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes);914ASSERT_EGL_SUCCESS();915ASSERT_NE(EGL_NO_SURFACE, firstPbufferSurface);916secondPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, pBufferAttributes);917ASSERT_EGL_SUCCESS();918ASSERT_NE(EGL_NO_SURFACE, secondPbufferSurface);919920initializeContext();921922// Use the same surface for both draw and read923EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext));924925// TODO(http://www.anglebug.com/6284): Failing with OpenGL ES backend on Android.926// Must be after the eglMakeCurrent() so the renderer string is initialized.927ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsAndroid());928929glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);930glClear(GL_COLOR_BUFFER_BIT);931ASSERT_GL_NO_ERROR();932EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);933934// Use different surfaces for draw and read, read should stay the same935EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, firstPbufferSurface, mContext));936glClearColor(GLColor::blue.R, GLColor::blue.G, GLColor::blue.B, GLColor::blue.A);937glClear(GL_COLOR_BUFFER_BIT);938ASSERT_GL_NO_ERROR();939EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);940// Verify draw surface was cleared941EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, secondPbufferSurface, secondPbufferSurface, mContext));942EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);943944EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, secondPbufferSurface, mContext));945ASSERT_EGL_SUCCESS();946947// Blit the source surface to the destination surface948glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);949ASSERT_GL_NO_ERROR();950EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, firstPbufferSurface, firstPbufferSurface, mContext));951EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);952}953954#if defined(ANGLE_ENABLE_D3D11)955class EGLSurfaceTestD3D11 : public EGLSurfaceTest956{};957958// Test that rendering to an IDCompositionSurface using a pbuffer works.959TEST_P(EGLSurfaceTestD3D11, CreateDirectCompositionSurface)960{961ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));962initializeDisplay();963964EGLAttrib device = 0;965EGLAttrib newEglDevice = 0;966ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));967ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),968EGL_D3D11_DEVICE_ANGLE, &device));969angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));970ASSERT_TRUE(!!d3d11Device);971972HMODULE dcompLibrary = LoadLibraryA("dcomp.dll");973if (!dcompLibrary)974{975std::cout << "DirectComposition not supported" << std::endl;976return;977}978typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE2)(IUnknown * dxgiDevice, REFIID iid,979void **dcompositionDevice);980PFN_DCOMPOSITION_CREATE_DEVICE2 createDComp = reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE2>(981GetProcAddress(dcompLibrary, "DCompositionCreateDevice2"));982if (!createDComp)983{984std::cout << "DirectComposition2 not supported" << std::endl;985FreeLibrary(dcompLibrary);986return;987}988989angle::ComPtr<IDCompositionDevice> dcompDevice;990HRESULT hr = createDComp(d3d11Device.Get(), IID_PPV_ARGS(dcompDevice.GetAddressOf()));991ASSERT_TRUE(SUCCEEDED(hr));992993angle::ComPtr<IDCompositionSurface> dcompSurface;994hr = dcompDevice->CreateSurface(100, 100, DXGI_FORMAT_B8G8R8A8_UNORM,995DXGI_ALPHA_MODE_PREMULTIPLIED, dcompSurface.GetAddressOf());996ASSERT_TRUE(SUCCEEDED(hr));997998angle::ComPtr<ID3D11Texture2D> texture;999POINT updateOffset;1000hr = dcompSurface->BeginDraw(nullptr, IID_PPV_ARGS(texture.GetAddressOf()), &updateOffset);1001ASSERT_TRUE(SUCCEEDED(hr));10021003const EGLint configAttributes[] = {1004EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,1005EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};10061007EGLConfig config;1008ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));10091010const EGLint surfaceAttributes[] = {EGL_WIDTH,1011100,1012EGL_HEIGHT,1013100,1014EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,1015EGL_TRUE,1016EGL_TEXTURE_OFFSET_X_ANGLE,1017updateOffset.x,1018EGL_TEXTURE_OFFSET_Y_ANGLE,1019updateOffset.y,1020EGL_NONE};10211022EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());1023mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,1024config, surfaceAttributes);1025ASSERT_EGL_SUCCESS();10261027mConfig = config;1028initializeContext();10291030eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);1031ASSERT_EGL_SUCCESS();10321033GLuint program = createProgram();1034ASSERT_NE(0u, program);1035drawWithProgram(program);1036EXPECT_GL_NO_ERROR();1037glDeleteProgram(program);1038}10391040TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithTextureOffset)1041{1042ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));1043initializeDisplay();10441045const EGLint configAttributes[] = {1046EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,1047EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};10481049EGLConfig config;1050ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));10511052mConfig = config;1053initializeContext();10541055EGLAttrib device = 0;1056EGLAttrib newEglDevice = 0;1057ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));1058ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),1059EGL_D3D11_DEVICE_ANGLE, &device));1060angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));1061ASSERT_TRUE(!!d3d11Device);10621063constexpr UINT kTextureWidth = 100;1064constexpr UINT kTextureHeight = 100;1065constexpr Color<uint8_t> kOpaqueBlack(0, 0, 0, 255);1066std::vector<Color<uint8_t>> textureData(kTextureWidth * kTextureHeight, kOpaqueBlack);10671068D3D11_SUBRESOURCE_DATA initialData = {};1069initialData.pSysMem = textureData.data();1070initialData.SysMemPitch = kTextureWidth * sizeof(kOpaqueBlack);10711072D3D11_TEXTURE2D_DESC desc = {};1073desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;1074desc.Width = kTextureWidth;1075desc.Height = kTextureHeight;1076desc.ArraySize = 1;1077desc.MipLevels = 1;1078desc.SampleDesc.Count = 1;1079desc.Usage = D3D11_USAGE_DEFAULT;1080desc.BindFlags = D3D11_BIND_RENDER_TARGET;1081angle::ComPtr<ID3D11Texture2D> texture;1082HRESULT hr = d3d11Device->CreateTexture2D(&desc, &initialData, &texture);1083ASSERT_TRUE(SUCCEEDED(hr));10841085angle::ComPtr<ID3D11DeviceContext> d3d11Context;1086d3d11Device->GetImmediateContext(&d3d11Context);10871088// Specify a texture offset of (50, 50) when rendering to the pbuffer surface.1089const EGLint surfaceAttributes[] = {EGL_WIDTH,1090kTextureWidth,1091EGL_HEIGHT,1092kTextureHeight,1093EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,1094EGL_TRUE,1095EGL_TEXTURE_OFFSET_X_ANGLE,109650,1097EGL_TEXTURE_OFFSET_Y_ANGLE,109850,1099EGL_NONE};1100EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());1101mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,1102config, surfaceAttributes);1103ASSERT_EGL_SUCCESS();11041105eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);1106ASSERT_EGL_SUCCESS();11071108// glClear should only clear subrect at offset (50, 50) without explicit scissor.1109glClearColor(0, 0, 1, 1); // Blue1110glClear(GL_COLOR_BUFFER_BIT);1111EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255);1112EXPECT_PIXEL_EQ(75, 75, 0, 0, 255, 255);1113EXPECT_GL_NO_ERROR();11141115// Drawing with a shader should also update the same subrect only without explicit viewport.1116GLuint program = createProgram(); // Red1117ASSERT_NE(0u, program);1118GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());1119glUseProgram(program);1120const GLfloat vertices[] = {1121-1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,1122-1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f,1123};1124glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);1125glEnableVertexAttribArray(positionLocation);1126glDrawArrays(GL_TRIANGLES, 0, 6);1127glDisableVertexAttribArray(positionLocation);1128glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);11291130EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255);1131EXPECT_PIXEL_EQ(75, 75, 255, 0, 0, 255);1132EXPECT_GL_NO_ERROR();11331134glDeleteProgram(program);1135EXPECT_GL_NO_ERROR();11361137// Blit framebuffer should also blit to the same subrect despite the dstX/Y arguments.1138GLRenderbuffer renderBuffer;1139glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);1140glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 50, 50);1141EXPECT_GL_NO_ERROR();11421143GLFramebuffer framebuffer;1144glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);1145glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);1146EXPECT_GL_NO_ERROR();11471148glClearColor(0, 1, 0, 1); // Green1149glClear(GL_COLOR_BUFFER_BIT);1150EXPECT_PIXEL_EQ(25, 25, 0, 255, 0, 255);1151EXPECT_GL_NO_ERROR();11521153glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0u);1154glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);1155glBlitFramebuffer(0, 0, 50, 50, 0, 0, 50, 50, GL_COLOR_BUFFER_BIT, GL_NEAREST);1156EXPECT_GL_NO_ERROR();11571158glBindFramebuffer(GL_READ_FRAMEBUFFER, 0u);1159EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255);1160EXPECT_PIXEL_EQ(75, 75, 0, 255, 0, 255);1161EXPECT_GL_NO_ERROR();1162}11631164TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithMSAA)1165{1166ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));11671168// clang-format off1169const EGLint configAttributes[] =1170{1171EGL_RED_SIZE, 8,1172EGL_GREEN_SIZE, 8,1173EGL_BLUE_SIZE, 8,1174EGL_ALPHA_SIZE, 0,1175EGL_DEPTH_SIZE, 0,1176EGL_STENCIL_SIZE, 0,1177EGL_SAMPLE_BUFFERS, 1,1178EGL_SAMPLES, 4,1179EGL_NONE1180};1181// clang-format on11821183initializeDisplay();1184EGLConfig config;1185if (EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config) == EGL_FALSE)1186{1187std::cout << "EGLConfig for 4xMSAA is not supported, skipping test" << std::endl;1188return;1189}11901191initializeSurface(config);11921193eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);1194ASSERT_EGL_SUCCESS();11951196GLuint program = createProgram();1197ASSERT_NE(0u, program);11981199glClearColor(0, 0, 0, 1);1200glClear(GL_COLOR_BUFFER_BIT);12011202GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());1203ASSERT_NE(-1, positionLocation);12041205glUseProgram(program);12061207const GLfloat halfPixelOffset = 0.5f * 2.0f / mOSWindow->getWidth();1208// clang-format off1209const GLfloat vertices[] =1210{1211-1.0f + halfPixelOffset, 1.0f, 0.5f,1212-1.0f + halfPixelOffset, -1.0f, 0.5f,12131.0f, -1.0f, 0.5f1214};1215// clang-format on12161217glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);1218glEnableVertexAttribArray(positionLocation);12191220glDrawArrays(GL_TRIANGLES, 0, 3);12211222glDisableVertexAttribArray(positionLocation);1223glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);12241225EXPECT_PIXEL_NEAR(0, 0, 127, 0, 0, 255, 10);1226EXPECT_GL_NO_ERROR();12271228glDeleteProgram(program);1229}12301231#endif // ANGLE_ENABLE_D3D1112321233// Verify bliting between two surfaces works correctly.1234TEST_P(EGLSurfaceTest3, BlitBetweenSurfaces)1235{1236initializeDisplay();1237ASSERT_NE(mDisplay, EGL_NO_DISPLAY);12381239initializeSurfaceWithDefaultConfig(true);1240ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);1241ASSERT_NE(mContext, EGL_NO_CONTEXT);12421243EGLSurface surface1;1244EGLSurface surface2;12451246const EGLint surfaceAttributes[] = {1247EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE,1248};12491250surface1 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);1251ASSERT_EGL_SUCCESS();1252surface2 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);1253ASSERT_EGL_SUCCESS();12541255// Clear surface1.1256EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface1, surface1, mContext));12571258// TODO(http://www.anglebug.com/6284): Failing with OpenGL ES backend on Android and Windows.1259// Must be after the eglMakeCurrent() so the renderer string is initialized.1260ANGLE_SKIP_TEST_IF(IsOpenGLES() && (IsAndroid() || IsWindows()));12611262glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);1263glClear(GL_COLOR_BUFFER_BIT);1264ASSERT_GL_NO_ERROR();12651266// Blit from surface1 to surface2.1267EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface1, mContext));1268glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);1269ASSERT_GL_NO_ERROR();12701271// Confirm surface1 has the clear color.1272EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface1, surface1, mContext));1273EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::red);12741275// Confirm surface2 has the blited clear color.1276EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface2, mContext));1277EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::red);12781279eglDestroySurface(mDisplay, surface1);1280eglDestroySurface(mDisplay, surface2);1281}12821283// Verify bliting between two surfaces works correctly.1284TEST_P(EGLSurfaceTest3, BlitBetweenSurfacesWithDeferredClear)1285{1286initializeDisplay();1287ASSERT_NE(mDisplay, EGL_NO_DISPLAY);12881289initializeSurfaceWithDefaultConfig(true);1290ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);1291ASSERT_NE(mContext, EGL_NO_CONTEXT);12921293EGLSurface surface1;1294EGLSurface surface2;12951296const EGLint surfaceAttributes[] = {1297EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE,1298};12991300surface1 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);1301ASSERT_EGL_SUCCESS();1302surface2 = eglCreatePbufferSurface(mDisplay, mConfig, surfaceAttributes);1303ASSERT_EGL_SUCCESS();13041305// Clear surface1.1306EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface1, surface1, mContext));13071308// TODO(http://www.anglebug.com/6284): Failing with OpenGL ES backend on Android and Windows.1309// Must be after the eglMakeCurrent() so the renderer string is initialized.1310ANGLE_SKIP_TEST_IF(IsOpenGLES() && (IsAndroid() || IsWindows()));13111312glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);1313glClear(GL_COLOR_BUFFER_BIT);1314ASSERT_GL_NO_ERROR();1315// Force the clear to be flushed1316EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::red);13171318// Clear to green, but don't read it back so the clear is deferred.1319glClearColor(GLColor::green.R, GLColor::green.G, GLColor::green.B, GLColor::green.A);1320glClear(GL_COLOR_BUFFER_BIT);1321ASSERT_GL_NO_ERROR();13221323// Blit from surface1 to surface2.1324EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface1, mContext));1325glBlitFramebuffer(0, 0, 64, 64, 0, 0, 64, 64, GL_COLOR_BUFFER_BIT, GL_NEAREST);1326ASSERT_GL_NO_ERROR();13271328// Confirm surface1 has the clear color.1329EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::green);13301331// Confirm surface2 has the blited clear color.1332EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface2, surface2, mContext));1333EXPECT_PIXEL_COLOR_EQ(32, 32, GLColor::green);13341335eglDestroySurface(mDisplay, surface1);1336eglDestroySurface(mDisplay, surface2);1337}13381339// Verify switching between a surface with robust resource init and one without still clears alpha.1340TEST_P(EGLSurfaceTest, RobustResourceInitAndEmulatedAlpha)1341{1342// http://anglebug.com/52791343ANGLE_SKIP_TEST_IF(IsNVIDIA() && isGLRenderer() && IsLinux());13441345// http://anglebug.com/52801346ANGLE_SKIP_TEST_IF(IsAndroid() && IsNexus5X() && isGLESRenderer());13471348initializeDisplay();1349ASSERT_NE(mDisplay, EGL_NO_DISPLAY);13501351ANGLE_SKIP_TEST_IF(1352!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_robust_resource_initialization"));13531354// Initialize and draw red to a Surface with robust resource init enabled.1355constexpr EGLint kRGBAAttributes[] = {EGL_RED_SIZE, 8,1356EGL_GREEN_SIZE, 8,1357EGL_BLUE_SIZE, 8,1358EGL_ALPHA_SIZE, 8,1359EGL_SURFACE_TYPE, EGL_WINDOW_BIT,1360EGL_NONE};13611362EGLint configCount = 0;1363EGLConfig rgbaConfig = nullptr;1364ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAAttributes, &rgbaConfig, 1, &configCount));1365ASSERT_EQ(configCount, 1);1366ASSERT_NE(rgbaConfig, nullptr);13671368std::vector<EGLint> robustInitAttribs;1369robustInitAttribs.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);1370robustInitAttribs.push_back(EGL_TRUE);13711372initializeSurfaceWithAttribs(rgbaConfig, robustInitAttribs);1373ASSERT_EGL_SUCCESS();1374ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);13751376initializeSingleContext(&mContext);1377ASSERT_EGL_SUCCESS();1378ASSERT_NE(mContext, EGL_NO_CONTEXT);13791380eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);1381ASSERT_EGL_SUCCESS();1382eglSwapBuffers(mDisplay, mWindowSurface);13831384// RGBA robust init setup complete. Draw red and verify.1385{1386ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());1387glUseProgram(program);13881389drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);1390ASSERT_GL_NO_ERROR();1391EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);13921393eglSwapBuffers(mDisplay, mWindowSurface);1394}13951396tearDownContextAndSurface();13971398// Create second RGB surface with robust resource disabled.1399constexpr EGLint kRGBAttributes[] = {EGL_RED_SIZE, 8,1400EGL_GREEN_SIZE, 8,1401EGL_BLUE_SIZE, 8,1402EGL_ALPHA_SIZE, 0,1403EGL_SURFACE_TYPE, EGL_WINDOW_BIT,1404EGL_NONE};14051406configCount = 0;1407EGLConfig rgbConfig = nullptr;1408ASSERT_EGL_TRUE(eglChooseConfig(mDisplay, kRGBAttributes, &rgbConfig, 1, &configCount));1409ASSERT_EQ(configCount, 1);1410ASSERT_NE(rgbConfig, nullptr);14111412initializeSurface(rgbConfig);1413ASSERT_EGL_SUCCESS();1414ASSERT_NE(mWindowSurface, EGL_NO_SURFACE);14151416initializeSingleContext(&mContext);1417ASSERT_EGL_SUCCESS();1418ASSERT_NE(mContext, EGL_NO_CONTEXT);14191420eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);1421ASSERT_EGL_SUCCESS();14221423// RGB non-robust init setup complete. Draw red and verify.1424{1425ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());1426glUseProgram(program);14271428drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);1429ASSERT_GL_NO_ERROR();1430EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);14311432eglSwapBuffers(mDisplay, mWindowSurface);1433}1434}14351436void EGLSurfaceTest::drawQuadThenTearDown()1437{1438initializeSingleContext(&mContext);14391440eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext);1441ASSERT_EGL_SUCCESS();14421443{1444ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());1445drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.5f);1446EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);1447eglSwapBuffers(mDisplay, mWindowSurface);1448ASSERT_EGL_SUCCESS();1449}14501451tearDownContextAndSurface();1452}14531454// Tests the EGL_ANGLE_create_surface_swap_interval extension if available.1455TEST_P(EGLSurfaceTest, CreateSurfaceSwapIntervalANGLE)1456{1457initializeDisplay();1458ASSERT_NE(mDisplay, EGL_NO_DISPLAY);14591460mConfig = chooseDefaultConfig(true);1461ASSERT_NE(mConfig, nullptr);14621463if (IsEGLDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_create_surface_swap_interval"))1464{1465// Test error conditions.1466EGLint minSwapInterval = 0;1467eglGetConfigAttrib(mDisplay, mConfig, EGL_MIN_SWAP_INTERVAL, &minSwapInterval);1468ASSERT_EGL_SUCCESS();14691470if (minSwapInterval > 0)1471{1472std::vector<EGLint> min1SwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, minSwapInterval - 1};1473initializeWindowSurfaceWithAttribs(mConfig, min1SwapAttribs, EGL_BAD_ATTRIBUTE);1474}14751476EGLint maxSwapInterval = 0;1477eglGetConfigAttrib(mDisplay, mConfig, EGL_MAX_SWAP_INTERVAL, &maxSwapInterval);1478ASSERT_EGL_SUCCESS();14791480if (maxSwapInterval < std::numeric_limits<EGLint>::max())1481{1482std::vector<EGLint> max1SwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, maxSwapInterval + 1};1483initializeWindowSurfaceWithAttribs(mConfig, max1SwapAttribs, EGL_BAD_ATTRIBUTE);1484}14851486// Test valid min/max usage.1487{1488std::vector<EGLint> minSwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, minSwapInterval};1489initializeWindowSurfaceWithAttribs(mConfig, minSwapAttribs, EGL_SUCCESS);1490drawQuadThenTearDown();1491}14921493if (minSwapInterval != maxSwapInterval)1494{1495std::vector<EGLint> maxSwapAttribs = {EGL_SWAP_INTERVAL_ANGLE, maxSwapInterval};1496initializeWindowSurfaceWithAttribs(mConfig, maxSwapAttribs, EGL_SUCCESS);1497drawQuadThenTearDown();1498}1499}1500else1501{1502// Test extension unavailable error.1503std::vector<EGLint> swapInterval1Attribs = {EGL_SWAP_INTERVAL_ANGLE, 1};1504initializeWindowSurfaceWithAttribs(mConfig, swapInterval1Attribs, EGL_BAD_ATTRIBUTE);1505}1506}1507} // anonymous namespace15081509ANGLE_INSTANTIATE_TEST(EGLSurfaceTest,1510WithNoFixture(ES2_D3D9()),1511WithNoFixture(ES2_D3D11()),1512WithNoFixture(ES3_D3D11()),1513WithNoFixture(ES2_OPENGL()),1514WithNoFixture(ES3_OPENGL()),1515WithNoFixture(ES2_OPENGLES()),1516WithNoFixture(ES3_OPENGLES()),1517WithNoFixture(ES2_VULKAN()),1518WithNoFixture(ES3_VULKAN()),1519WithNoFixture(ES2_VULKAN_SWIFTSHADER()),1520WithNoFixture(ES3_VULKAN_SWIFTSHADER()));15211522GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLFloatSurfaceTest);1523ANGLE_INSTANTIATE_TEST(EGLFloatSurfaceTest,1524WithNoFixture(ES2_OPENGL()),1525WithNoFixture(ES3_OPENGL()),1526WithNoFixture(ES2_VULKAN()),1527WithNoFixture(ES3_VULKAN()));15281529GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLSurfaceTest3);1530ANGLE_INSTANTIATE_TEST(EGLSurfaceTest3,1531WithNoFixture(ES3_D3D11()),1532WithNoFixture(ES3_OPENGLES()),1533WithNoFixture(ES3_VULKAN()),1534WithNoFixture(ES3_VULKAN_SWIFTSHADER()));15351536#if defined(ANGLE_ENABLE_D3D11)1537ANGLE_INSTANTIATE_TEST(EGLSurfaceTestD3D11, WithNoFixture(ES2_D3D11()), WithNoFixture(ES3_D3D11()));1538#endif153915401541