Path: blob/main_old/src/tests/egl_tests/EGLSurfacelessContextTest.cpp
1693 views
//1// Copyright 2017 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//56// EGLSurfacelessContextTest.cpp:7// Tests for the EGL_KHR_surfaceless_context and GL_OES_surfaceless_context89#include <gtest/gtest.h>1011#include "test_utils/ANGLETest.h"12#include "test_utils/angle_test_configs.h"13#include "test_utils/gl_raii.h"1415using namespace angle;1617namespace18{1920class EGLSurfacelessContextTest : public ANGLETest21{22public:23EGLSurfacelessContextTest() : mDisplay(0) {}2425void testSetUp() override26{27EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};28mDisplay = eglGetPlatformDisplayEXT(29EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);30ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY);3132ASSERT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));3334int nConfigs = 0;35ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &nConfigs));36ASSERT_TRUE(nConfigs != 0);3738int nReturnedConfigs = 0;39std::vector<EGLConfig> configs(nConfigs);40ASSERT_EGL_TRUE(eglGetConfigs(mDisplay, configs.data(), nConfigs, &nReturnedConfigs));41ASSERT_TRUE(nConfigs == nReturnedConfigs);4243for (auto config : configs)44{45EGLint surfaceType;46eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType);47if (surfaceType & EGL_PBUFFER_BIT)48{49mConfig = config;50mSupportsPbuffers = true;51break;52}53}5455if (!mConfig)56{57mConfig = configs[0];58}5960ASSERT_NE(nullptr, mConfig);61}6263void testTearDown() override64{65eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);6667if (mContext != EGL_NO_CONTEXT)68{69eglDestroyContext(mDisplay, mContext);70}7172if (mPbuffer != EGL_NO_SURFACE)73{74eglDestroySurface(mDisplay, mPbuffer);75}7677eglTerminate(mDisplay);78}7980protected:81EGLContext createContext()82{83const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};8485mContext = eglCreateContext(mDisplay, mConfig, EGL_NO_CONTEXT, contextAttribs);86EXPECT_TRUE(mContext != EGL_NO_CONTEXT);87return mContext;88}8990EGLSurface createPbuffer(int width, int height)91{92if (!mSupportsPbuffers)93{94return EGL_NO_SURFACE;95}9697const EGLint pbufferAttribs[] = {98EGL_WIDTH, 500, EGL_HEIGHT, 500, EGL_NONE,99};100mPbuffer = eglCreatePbufferSurface(mDisplay, mConfig, pbufferAttribs);101EXPECT_TRUE(mPbuffer != EGL_NO_SURFACE);102return mPbuffer;103}104105void createFramebuffer(GLFramebuffer *fbo, GLTexture *tex) const106{107glBindFramebuffer(GL_FRAMEBUFFER, fbo->get());108109glBindTexture(GL_TEXTURE_2D, tex->get());110glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 500, 500, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);111112glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->get(), 0);113ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);114}115116bool checkExtension(bool verbose = true) const117{118if (!IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_surfaceless_context"))119{120if (verbose)121{122std::cout << "Test skipped because EGL_KHR_surfaceless_context is not available."123<< std::endl;124}125return false;126}127return true;128}129130EGLContext mContext = EGL_NO_CONTEXT;131EGLSurface mPbuffer = EGL_NO_SURFACE;132bool mSupportsPbuffers = false;133EGLConfig mConfig = 0;134EGLDisplay mDisplay = EGL_NO_DISPLAY;135};136137// Test surfaceless MakeCurrent returns the correct value.138TEST_P(EGLSurfacelessContextTest, MakeCurrentSurfaceless)139{140EGLContext context = createContext();141142if (eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context))143{144ASSERT_TRUE(checkExtension(false));145}146else147{148// The extension allows EGL_BAD_MATCH with the extension too, but ANGLE149// shouldn't do that.150ASSERT_FALSE(checkExtension(false));151}152}153154// Test that the scissor and viewport are set correctly155TEST_P(EGLSurfacelessContextTest, DefaultScissorAndViewport)156{157if (!checkExtension())158{159return;160}161162EGLContext context = createContext();163ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));164165GLint scissor[4] = {1, 2, 3, 4};166glGetIntegerv(GL_SCISSOR_BOX, scissor);167ASSERT_GL_NO_ERROR();168ASSERT_EQ(0, scissor[0]);169ASSERT_EQ(0, scissor[1]);170ASSERT_EQ(0, scissor[2]);171ASSERT_EQ(0, scissor[3]);172173GLint viewport[4] = {1, 2, 3, 4};174glGetIntegerv(GL_VIEWPORT, viewport);175ASSERT_GL_NO_ERROR();176ASSERT_EQ(0, viewport[0]);177ASSERT_EQ(0, viewport[1]);178ASSERT_EQ(0, viewport[2]);179ASSERT_EQ(0, viewport[3]);180}181182// Test the CheckFramebufferStatus returns the correct value.183TEST_P(EGLSurfacelessContextTest, CheckFramebufferStatus)184{185if (!checkExtension())186{187return;188}189190EGLContext context = createContext();191ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));192193ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_UNDEFINED_OES, glCheckFramebufferStatus(GL_FRAMEBUFFER));194195GLFramebuffer fbo;196GLTexture tex;197createFramebuffer(&fbo, &tex);198glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());199ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);200}201202// Test that clearing and readpixels work when done in an FBO.203TEST_P(EGLSurfacelessContextTest, ClearReadPixelsInFBO)204{205if (!checkExtension())206{207return;208}209210EGLContext context = createContext();211ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));212213GLFramebuffer fbo;214GLTexture tex;215createFramebuffer(&fbo, &tex);216glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());217218glClearColor(1.0f, 0.0f, 0.0f, 1.0f);219glClear(GL_COLOR_BUFFER_BIT);220ASSERT_GL_NO_ERROR();221222EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::red);223ASSERT_GL_NO_ERROR();224}225226// Test clear+readpixels in an FBO in surfaceless and in the default FBO in a pbuffer227TEST_P(EGLSurfacelessContextTest, Switcheroo)228{229ANGLE_SKIP_TEST_IF(!checkExtension());230ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);231232// Fails on NVIDIA Shield TV (http://anglebug.com/4924)233ANGLE_SKIP_TEST_IF(IsAndroid() && IsNVIDIA());234235EGLContext context = createContext();236EGLSurface pbuffer = createPbuffer(500, 500);237238// We need to make the context current to do the one time setup of the FBO239ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));240GLFramebuffer fbo;241GLTexture tex;242createFramebuffer(&fbo, &tex);243glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());244245for (int i = 0; i < 4; ++i)246{247// Clear to red in the FBO in surfaceless mode248ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context));249250glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());251glClearColor(1.0f, 0.0f, 0.0f, 1.0f);252glClear(GL_COLOR_BUFFER_BIT);253ASSERT_GL_NO_ERROR();254255EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::red);256ASSERT_GL_NO_ERROR();257258// Clear to green in the pbuffer259ASSERT_EGL_TRUE(eglMakeCurrent(mDisplay, pbuffer, pbuffer, context));260261glBindFramebuffer(GL_FRAMEBUFFER, 0);262glClearColor(0.0f, 1.0f, 0.0f, 1.0f);263glClear(GL_COLOR_BUFFER_BIT);264ASSERT_GL_NO_ERROR();265266EXPECT_PIXEL_COLOR_EQ(250, 250, GLColor::green);267ASSERT_GL_NO_ERROR();268}269}270271} // anonymous namespace272273ANGLE_INSTANTIATE_TEST(EGLSurfacelessContextTest,274WithNoFixture(ES2_D3D9()),275WithNoFixture(ES2_D3D11()),276WithNoFixture(ES2_METAL()),277WithNoFixture(ES2_OPENGL()),278WithNoFixture(ES2_OPENGLES()),279WithNoFixture(ES2_VULKAN()));280281282