| // |
| // 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 <gtest/gtest.h> |
| #include <EGL/egl.h> |
| #include <EGL/eglext.h> |
| #include <GLES2/gl2.h> |
| |
| #include "common/angleutils.h" |
| #include "OSWindow.h" |
| |
| namespace |
| { |
| |
| class EGLSurfaceTest : public testing::Test |
| { |
| 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 SetUp() override |
| { |
| mOSWindow = CreateOSWindow(); |
| mOSWindow->initialize("EGLSurfaceTest", 64, 64); |
| } |
| |
| // Release any resources created in the test body |
| void TearDown() override |
| { |
| mOSWindow->destroy(); |
| SafeDelete(mOSWindow); |
| |
| if (mDisplay != EGL_NO_DISPLAY) |
| { |
| 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; |
| } |
| |
| eglTerminate(mDisplay); |
| mDisplay = EGL_NO_DISPLAY; |
| } |
| |
| ASSERT_TRUE(mWindowSurface == EGL_NO_SURFACE && mContext == EGL_NO_CONTEXT); |
| } |
| |
| void initializeSurface(EGLenum platformType) |
| { |
| PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT")); |
| ASSERT_TRUE(eglGetPlatformDisplayEXT != nullptr); |
| |
| const EGLint displayAttributes[] = |
| { |
| EGL_PLATFORM_ANGLE_TYPE_ANGLE, platformType, |
| EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE, |
| EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE, |
| EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, |
| EGL_NONE, |
| }; |
| |
| mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, mOSWindow->getNativeDisplay(), displayAttributes); |
| ASSERT_TRUE(mDisplay != EGL_NO_DISPLAY); |
| |
| EGLint majorVersion, minorVersion; |
| ASSERT_TRUE(eglInitialize(mDisplay, &majorVersion, &minorVersion) == EGL_TRUE); |
| |
| eglBindAPI(EGL_OPENGL_ES_API); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| 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_NONE |
| }; |
| |
| EGLint configCount; |
| ASSERT_TRUE(eglChooseConfig(mDisplay, configAttributes, &mConfig, 1, &configCount) || (configCount != 1) == EGL_TRUE); |
| |
| std::vector<EGLint> surfaceAttributes; |
| surfaceAttributes.push_back(EGL_NONE); |
| surfaceAttributes.push_back(EGL_NONE); |
| |
| // Create first window surface |
| mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), &surfaceAttributes[0]); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| mPbufferSurface = eglCreatePbufferSurface(mDisplay, mConfig, &surfaceAttributes[0]); |
| |
| EGLint contextAttibutes[] = |
| { |
| EGL_CONTEXT_CLIENT_VERSION, 2, |
| EGL_NONE |
| }; |
| |
| mContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| mSecondContext = eglCreateContext(mDisplay, mConfig, nullptr, contextAttibutes); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| } |
| |
| void runMessageLoopTest(EGLSurface secondSurface, EGLContext secondContext) |
| { |
| eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| // Make a second context current |
| eglMakeCurrent(mDisplay, secondSurface, secondSurface, secondContext); |
| eglDestroySurface(mDisplay, mWindowSurface); |
| |
| // Create second window surface |
| std::vector<EGLint> surfaceAttributes; |
| surfaceAttributes.push_back(EGL_NONE); |
| surfaceAttributes.push_back(EGL_NONE); |
| |
| mWindowSurface = eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), &surfaceAttributes[0]); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); |
| ASSERT_TRUE(eglGetError() == 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; |
| }; |
| |
| // Test a surface bug where we could have two Window surfaces active |
| // at one time, blocking message loops. See http://crbug.com/475085 |
| TEST_F(EGLSurfaceTest, MessageLoopBug) |
| { |
| const char *extensionsString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); |
| if (strstr(extensionsString, "EGL_ANGLE_platform_angle_d3d") == nullptr) |
| { |
| std::cout << "D3D Platform not supported in ANGLE"; |
| return; |
| } |
| |
| initializeSurface(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE); |
| |
| runMessageLoopTest(EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| } |
| |
| // Tests the message loop bug, but with setting a second context |
| // instead of null. |
| TEST_F(EGLSurfaceTest, MessageLoopBugContext) |
| { |
| const char *extensionsString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); |
| if (strstr(extensionsString, "EGL_ANGLE_platform_angle_d3d") == nullptr) |
| { |
| std::cout << "D3D Platform not supported in ANGLE"; |
| return; |
| } |
| |
| initializeSurface(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE); |
| |
| runMessageLoopTest(mPbufferSurface, mSecondContext); |
| } |
| |
| // Test a bug where calling makeCurrent twice would release the surface |
| TEST_F(EGLSurfaceTest, MakeCurrentTwice) |
| { |
| initializeSurface(EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); |
| |
| eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext); |
| ASSERT_TRUE(eglGetError() == EGL_SUCCESS); |
| |
| // Simple operation to test the FBO is set appropriately |
| glClear(GL_COLOR_BUFFER_BIT); |
| } |
| |
| } |