• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include <gtest/gtest.h>
8 #include <vector>
9 
10 #include "test_utils/ANGLETest.h"
11 
12 using namespace angle;
13 
14 class EGLDisplayTest : public ANGLETest<>
15 {
16   protected:
chooseConfig(EGLDisplay display)17     EGLConfig chooseConfig(EGLDisplay display)
18     {
19         const EGLint attribs[] = {EGL_RED_SIZE,
20                                   8,
21                                   EGL_GREEN_SIZE,
22                                   8,
23                                   EGL_BLUE_SIZE,
24                                   8,
25                                   EGL_ALPHA_SIZE,
26                                   8,
27                                   EGL_RENDERABLE_TYPE,
28                                   EGL_OPENGL_ES2_BIT,
29                                   EGL_SURFACE_TYPE,
30                                   EGL_PBUFFER_BIT,
31                                   EGL_NONE};
32         EGLConfig config       = EGL_NO_CONFIG_KHR;
33         EGLint count           = 0;
34         EXPECT_EGL_TRUE(eglChooseConfig(display, attribs, &config, 1, &count));
35         EXPECT_EGL_TRUE(count > 0);
36         return config;
37     }
38 
createContext(EGLDisplay display,EGLConfig config)39     EGLContext createContext(EGLDisplay display, EGLConfig config)
40     {
41         const EGLint attribs[] = {EGL_CONTEXT_MAJOR_VERSION, 2, EGL_NONE};
42         EGLContext context     = eglCreateContext(display, config, nullptr, attribs);
43         EXPECT_NE(context, EGL_NO_CONTEXT);
44         return context;
45     }
46 
createSurface(EGLDisplay display,EGLConfig config)47     EGLSurface createSurface(EGLDisplay display, EGLConfig config)
48     {
49         const EGLint attribs[] = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
50         EGLSurface surface     = eglCreatePbufferSurface(display, config, attribs);
51         EXPECT_NE(surface, EGL_NO_SURFACE);
52         return surface;
53     }
54 };
55 
56 // Tests that an eglInitialize can be re-initialized.  The spec says:
57 //
58 // > Initializing an already-initialized display is allowed, but the only effect of such a call is
59 // to return EGL_TRUE and update the EGL version numbers
TEST_P(EGLDisplayTest,InitializeMultipleTimes)60 TEST_P(EGLDisplayTest, InitializeMultipleTimes)
61 {
62     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
63     EGLint major = 0, minor = 0;
64     EXPECT_EGL_TRUE(eglInitialize(display, &major, &minor) != EGL_FALSE);
65     for (uint32_t i = 0; i < 10; ++i)
66     {
67         EGLint retryMajor = 123456, retryMinor = -1;
68         EXPECT_EGL_TRUE(eglInitialize(display, &retryMajor, &retryMinor) != EGL_FALSE);
69         EXPECT_EQ(major, retryMajor) << i;
70         EXPECT_EQ(minor, retryMinor) << i;
71     }
72 }
73 
74 // Test that call eglInitialize() in parallel in multiple threads works
75 // > Initializing an already-initialized display is allowed, but the only effect
76 // of such a call is to return EGL_TRUE and update the EGL version numbers
TEST_P(EGLDisplayTest,InitializeMultipleTimesInDifferentThreads)77 TEST_P(EGLDisplayTest, InitializeMultipleTimesInDifferentThreads)
78 {
79     std::array<std::thread, 10> threads;
80     for (std::thread &thread : threads)
81     {
82         thread = std::thread([&]() {
83             EGLDisplay display                 = eglGetDisplay(EGL_DEFAULT_DISPLAY);
84             const int INVALID_GL_MAJOR_VERSION = -1;
85             const int INVALID_GL_MINOR_VERSION = -1;
86             EGLint threadMajor                 = INVALID_GL_MAJOR_VERSION;
87             EGLint threadMinor                 = INVALID_GL_MINOR_VERSION;
88             EXPECT_EGL_TRUE(eglInitialize(display, &threadMajor, &threadMinor) != EGL_FALSE);
89             EXPECT_NE(threadMajor, INVALID_GL_MAJOR_VERSION);
90             EXPECT_NE(threadMinor, INVALID_GL_MINOR_VERSION);
91         });
92     }
93 
94     for (std::thread &thread : threads)
95     {
96         thread.join();
97     }
98 }
99 
100 // Tests that an EGLDisplay can be re-initialized.
TEST_P(EGLDisplayTest,InitializeTerminateInitialize)101 TEST_P(EGLDisplayTest, InitializeTerminateInitialize)
102 {
103     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
104     EXPECT_EGL_TRUE(eglInitialize(display, nullptr, nullptr) != EGL_FALSE);
105     EXPECT_EGL_TRUE(eglTerminate(display) != EGL_FALSE);
106     EXPECT_EGL_TRUE(eglInitialize(display, nullptr, nullptr) != EGL_FALSE);
107 }
108 
109 // Tests current Context leaking when call eglTerminate() while it is current.
TEST_P(EGLDisplayTest,ContextLeakAfterTerminate)110 TEST_P(EGLDisplayTest, ContextLeakAfterTerminate)
111 {
112     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
113     EXPECT_EGL_TRUE(eglInitialize(display, nullptr, nullptr));
114 
115     EGLConfig config   = chooseConfig(display);
116     EGLContext context = createContext(display, config);
117     EGLSurface surface = createSurface(display, config);
118 
119     // Make "context" current.
120     EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context));
121 
122     // Terminate display while "context" is current.
123     EXPECT_EGL_TRUE(eglTerminate(display));
124 
125     // Unmake "context" from current and allow Display to actually terminate.
126     (void)eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
127 
128     // Get EGLDisplay again.
129     display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
130 
131     // Check if Display was actually terminated.
132     EGLint val;
133     EXPECT_EGL_FALSE(eglQueryContext(display, context, EGL_CONTEXT_CLIENT_TYPE, &val));
134     EXPECT_EQ(eglGetError(), EGL_NOT_INITIALIZED);
135 }
136 
137 ANGLE_INSTANTIATE_TEST(EGLDisplayTest,
138                        WithNoFixture(ES2_D3D9()),
139                        WithNoFixture(ES2_D3D11()),
140                        WithNoFixture(ES2_OPENGL()),
141                        WithNoFixture(ES2_VULKAN()),
142                        WithNoFixture(ES3_D3D11()),
143                        WithNoFixture(ES3_OPENGL()),
144                        WithNoFixture(ES3_VULKAN()));
145