| // | |
| // 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. | |
| // | |
| // EGLX11VisualTest.cpp: tests for EGL_ANGLE_x11_visual extension | |
| #include <gtest/gtest.h> | |
| #include <EGL/egl.h> | |
| #include <EGL/eglext.h> | |
| #include <X11/Xlib.h> | |
| #include "test_utils/ANGLETest.h" | |
| #include "util/OSWindow.h" | |
| #include "util/x11/X11Window.h" | |
| using namespace angle; | |
| namespace | |
| { | |
| const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; | |
| } | |
| class EGLX11VisualHintTest : public ANGLETest | |
| { | |
| public: | |
| void testSetUp() override { mDisplay = XOpenDisplay(nullptr); } | |
| std::vector<EGLint> getDisplayAttributes(int visualId) const | |
| { | |
| std::vector<EGLint> attribs; | |
| attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); | |
| attribs.push_back(GetParam().getRenderer()); | |
| attribs.push_back(EGL_X11_VISUAL_ID_ANGLE); | |
| attribs.push_back(visualId); | |
| attribs.push_back(EGL_NONE); | |
| return attribs; | |
| } | |
| unsigned int chooseDifferentVisual(unsigned int visualId) | |
| { | |
| int numVisuals; | |
| XVisualInfo visualTemplate; | |
| visualTemplate.screen = DefaultScreen(mDisplay); | |
| XVisualInfo *visuals = | |
| XGetVisualInfo(mDisplay, VisualScreenMask, &visualTemplate, &numVisuals); | |
| EXPECT_TRUE(numVisuals >= 2); | |
| for (int i = 0; i < numVisuals; ++i) | |
| { | |
| if (visuals[i].visualid != visualId) | |
| { | |
| int result = visuals[i].visualid; | |
| XFree(visuals); | |
| return result; | |
| } | |
| } | |
| EXPECT_TRUE(false); | |
| return -1; | |
| } | |
| protected: | |
| Display *mDisplay; | |
| }; | |
| // Test that display creation fails if the visual ID passed in invalid. | |
| TEST_P(EGLX11VisualHintTest, InvalidVisualID) | |
| { | |
| static const int gInvalidVisualId = -1; | |
| auto attributes = getDisplayAttributes(gInvalidVisualId); | |
| EGLDisplay display = | |
| eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attributes.data()); | |
| ASSERT_TRUE(display != EGL_NO_DISPLAY); | |
| ASSERT_TRUE(EGL_FALSE == eglInitialize(display, nullptr, nullptr)); | |
| ASSERT_EGL_ERROR(EGL_NOT_INITIALIZED); | |
| } | |
| // Test that context creation with a visual ID succeeds, that the context exposes | |
| // only one config, and that a clear on a surface with this config works. | |
| TEST_P(EGLX11VisualHintTest, ValidVisualIDAndClear) | |
| { | |
| // We'll test the extension with one visual ID but we don't care which one. This means we | |
| // can use OSWindow to create a window and just grab its visual. | |
| OSWindow *osWindow = OSWindow::New(); | |
| osWindow->initialize("EGLX11VisualHintTest", 500, 500); | |
| osWindow->setVisible(true); | |
| Window xWindow = osWindow->getNativeWindow(); | |
| XWindowAttributes windowAttributes; | |
| ASSERT_NE(0, XGetWindowAttributes(mDisplay, xWindow, &windowAttributes)); | |
| int visualId = windowAttributes.visual->visualid; | |
| auto attributes = getDisplayAttributes(visualId); | |
| EGLDisplay display = | |
| eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attributes.data()); | |
| ASSERT_NE(EGL_NO_DISPLAY, display); | |
| ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr)); | |
| // While this is not required by the extension, test that our implementation returns only one | |
| // config, with the same native visual Id that we provided. | |
| int nConfigs = 0; | |
| ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, nullptr, 0, &nConfigs)); | |
| ASSERT_EQ(1, nConfigs); | |
| int nReturnedConfigs = 0; | |
| EGLConfig config; | |
| ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, &config, 1, &nReturnedConfigs)); | |
| ASSERT_EQ(nConfigs, nReturnedConfigs); | |
| EGLint eglNativeId; | |
| ASSERT_TRUE(EGL_TRUE == | |
| eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &eglNativeId)); | |
| ASSERT_EQ(visualId, eglNativeId); | |
| // Finally, try to do a clear on the window. | |
| EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); | |
| ASSERT_NE(EGL_NO_CONTEXT, context); | |
| EGLSurface window = eglCreateWindowSurface(display, config, xWindow, nullptr); | |
| ASSERT_EGL_SUCCESS(); | |
| eglMakeCurrent(display, window, window, context); | |
| ASSERT_EGL_SUCCESS(); | |
| glViewport(0, 0, 500, 500); | |
| glClearColor(0.0f, 0.0f, 1.0f, 1.0f); | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| ASSERT_GL_NO_ERROR(); | |
| EXPECT_PIXEL_EQ(250, 250, 0, 0, 255, 255); | |
| // Teardown | |
| eglDestroySurface(display, window); | |
| ASSERT_EGL_SUCCESS(); | |
| eglDestroyContext(display, context); | |
| ASSERT_EGL_SUCCESS(); | |
| OSWindow::Delete(&osWindow); | |
| eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
| eglTerminate(display); | |
| } | |
| // Test that EGL_BAD_MATCH is generated when trying to create an EGL window from | |
| // an X11 window whose visual ID doesn't match the visual ID passed at display creation. | |
| TEST_P(EGLX11VisualHintTest, InvalidWindowVisualID) | |
| { | |
| // Get the default visual ID, as a good guess of a visual id for which display | |
| // creation will succeed. | |
| int visualId; | |
| { | |
| OSWindow *osWindow = OSWindow::New(); | |
| osWindow->initialize("EGLX11VisualHintTest", 500, 500); | |
| osWindow->setVisible(true); | |
| Window xWindow = osWindow->getNativeWindow(); | |
| XWindowAttributes windowAttributes; | |
| ASSERT_NE(0, XGetWindowAttributes(mDisplay, xWindow, &windowAttributes)); | |
| visualId = windowAttributes.visual->visualid; | |
| OSWindow::Delete(&osWindow); | |
| } | |
| auto attributes = getDisplayAttributes(visualId); | |
| EGLDisplay display = | |
| eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, attributes.data()); | |
| ASSERT_NE(EGL_NO_DISPLAY, display); | |
| ASSERT_TRUE(EGL_TRUE == eglInitialize(display, nullptr, nullptr)); | |
| // Initialize the window with a visual id different from the display's visual id | |
| int otherVisualId = chooseDifferentVisual(visualId); | |
| ASSERT_NE(visualId, otherVisualId); | |
| OSWindow *osWindow = new X11Window(otherVisualId); | |
| osWindow->initialize("EGLX11VisualHintTest", 500, 500); | |
| osWindow->setVisible(true); | |
| Window xWindow = osWindow->getNativeWindow(); | |
| // Creating the EGL window should fail with EGL_BAD_MATCH | |
| int nReturnedConfigs = 0; | |
| EGLConfig config; | |
| ASSERT_TRUE(EGL_TRUE == eglGetConfigs(display, &config, 1, &nReturnedConfigs)); | |
| ASSERT_EQ(1, nReturnedConfigs); | |
| EGLSurface window = eglCreateWindowSurface(display, config, xWindow, nullptr); | |
| ASSERT_EQ(EGL_NO_SURFACE, window); | |
| ASSERT_EGL_ERROR(EGL_BAD_MATCH); | |
| OSWindow::Delete(&osWindow); | |
| } | |
| ANGLE_INSTANTIATE_TEST(EGLX11VisualHintTest, WithNoFixture(ES2_OPENGL())); |