• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 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 // EGLSyncTest.cpp:
7 //   Tests of EGL_KHR_fence_sync and EGL_KHR_wait_sync extensions.
8 
9 #include <gtest/gtest.h>
10 
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/angle_test_configs.h"
13 #include "util/EGLWindow.h"
14 
15 using namespace angle;
16 
17 class EGLSyncTest : public ANGLETest
18 {
19   protected:
hasFenceSyncExtension() const20     bool hasFenceSyncExtension() const
21     {
22         return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_fence_sync");
23     }
hasWaitSyncExtension() const24     bool hasWaitSyncExtension() const
25     {
26         return hasFenceSyncExtension() &&
27                IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_wait_sync");
28     }
hasGLSyncExtension() const29     bool hasGLSyncExtension() const { return IsGLExtensionEnabled("GL_OES_EGL_sync"); }
30 };
31 
32 // Test error cases for all EGL_KHR_fence_sync functions
TEST_P(EGLSyncTest,FenceSyncErrors)33 TEST_P(EGLSyncTest, FenceSyncErrors)
34 {
35     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
36 
37     EGLDisplay display = getEGLWindow()->getDisplay();
38 
39     // If the client API doesn't have the necessary extension, test that sync creation fails and
40     // ignore the rest of the tests.
41     if (!hasGLSyncExtension())
42     {
43         EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr));
44         EXPECT_EGL_ERROR(EGL_BAD_MATCH);
45     }
46 
47     ANGLE_SKIP_TEST_IF(!hasGLSyncExtension());
48 
49     EGLContext context     = eglGetCurrentContext();
50     EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);
51     EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);
52 
53     EXPECT_NE(context, EGL_NO_CONTEXT);
54     EXPECT_NE(drawSurface, EGL_NO_SURFACE);
55     EXPECT_NE(readSurface, EGL_NO_SURFACE);
56 
57     // CreateSync with no attribute shouldn't cause an error
58     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
59     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
60 
61     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
62 
63     // CreateSync with empty attribute shouldn't cause an error
64     const EGLint emptyAttributes[] = {EGL_NONE};
65     sync                           = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, emptyAttributes);
66     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
67 
68     // DestroySync generates BAD_PARAMETER if the sync is not valid
69     EXPECT_EGL_FALSE(eglDestroySyncKHR(display, reinterpret_cast<EGLSyncKHR>(20)));
70     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
71 
72     // CreateSync generates BAD_DISPLAY if display is not valid
73     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(EGL_NO_DISPLAY, EGL_SYNC_FENCE_KHR, nullptr));
74     EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
75 
76     // CreateSync generates BAD_ATTRIBUTE if attribute is neither nullptr nor empty.
77     const EGLint nonEmptyAttributes[] = {
78         EGL_CL_EVENT_HANDLE,
79         0,
80         EGL_NONE,
81     };
82     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nonEmptyAttributes));
83     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
84 
85     // CreateSync generates BAD_ATTRIBUTE if type is not valid
86     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, 0, nullptr));
87     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
88 
89     // CreateSync generates BAD_MATCH if no context is current
90     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
91     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr));
92     EXPECT_EGL_ERROR(EGL_BAD_MATCH);
93     eglMakeCurrent(display, drawSurface, readSurface, context);
94 
95     // ClientWaitSync generates EGL_BAD_PARAMETER if the sync object is not valid
96     EXPECT_EGL_FALSE(eglClientWaitSyncKHR(display, reinterpret_cast<EGLSyncKHR>(30), 0, 0));
97     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
98 
99     // GetSyncAttrib generates EGL_BAD_PARAMETER if the sync object is not valid, and value is not
100     // modified
101     constexpr EGLint kSentinelAttribValue = 123456789;
102     EGLint attribValue                    = kSentinelAttribValue;
103     EXPECT_EGL_FALSE(eglGetSyncAttribKHR(display, reinterpret_cast<EGLSyncKHR>(40),
104                                          EGL_SYNC_TYPE_KHR, &attribValue));
105     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
106     EXPECT_EQ(attribValue, kSentinelAttribValue);
107 
108     // GetSyncAttrib generates EGL_BAD_ATTRIBUTE if the attribute is not valid, and value is not
109     // modified
110     EXPECT_EGL_FALSE(eglGetSyncAttribKHR(display, sync, EGL_CL_EVENT_HANDLE, &attribValue));
111     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
112     EXPECT_EQ(attribValue, kSentinelAttribValue);
113 
114     // GetSyncAttrib generates EGL_BAD_MATCH if the attribute is valid for sync, but not the
115     // particular sync type. We don't have such a case at the moment.
116 
117     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
118 }
119 
120 // Test error cases for all EGL_KHR_wait_sync functions
TEST_P(EGLSyncTest,WaitSyncErrors)121 TEST_P(EGLSyncTest, WaitSyncErrors)
122 {
123     // The client API that shows support for eglWaitSyncKHR is the same as the one required for
124     // eglCreateSyncKHR.  As such, there is no way to create a sync and not be able to wait on it.
125     // This would have created an EGL_BAD_MATCH error.
126     ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
127 
128     EGLDisplay display     = getEGLWindow()->getDisplay();
129     EGLContext context     = eglGetCurrentContext();
130     EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);
131     EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);
132 
133     EXPECT_NE(context, EGL_NO_CONTEXT);
134     EXPECT_NE(drawSurface, EGL_NO_SURFACE);
135     EXPECT_NE(readSurface, EGL_NO_SURFACE);
136 
137     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
138     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
139 
140     // WaitSync generates BAD_MATCH if no context is current
141     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
142     EXPECT_EGL_FALSE(eglWaitSyncKHR(display, sync, 0));
143     EXPECT_EGL_ERROR(EGL_BAD_MATCH);
144     eglMakeCurrent(display, drawSurface, readSurface, context);
145 
146     // WaitSync generates BAD_PARAMETER if the sync is not valid
147     EXPECT_EGL_FALSE(eglWaitSyncKHR(display, reinterpret_cast<EGLSyncKHR>(20), 0));
148     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
149 
150     // WaitSync generates BAD_PARAMETER if flags is non-zero
151     EXPECT_EGL_FALSE(eglWaitSyncKHR(display, sync, 1));
152     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
153 
154     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
155 }
156 
157 // Test usage of eglGetSyncAttribKHR
TEST_P(EGLSyncTest,GetSyncAttrib)158 TEST_P(EGLSyncTest, GetSyncAttrib)
159 {
160     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
161 
162     EGLDisplay display = getEGLWindow()->getDisplay();
163 
164     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
165     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
166 
167     // Fence sync attributes are:
168     //
169     // EGL_SYNC_TYPE_KHR: EGL_SYNC_FENCE_KHR
170     // EGL_SYNC_STATUS_KHR: EGL_UNSIGNALED_KHR or EGL_SIGNALED_KHR
171     // EGL_SYNC_CONDITION_KHR: EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
172 
173     constexpr EGLint kSentinelAttribValue = 123456789;
174     EGLint attribValue                    = kSentinelAttribValue;
175     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_TYPE_KHR, &attribValue));
176     EXPECT_EQ(attribValue, EGL_SYNC_FENCE_KHR);
177 
178     attribValue = kSentinelAttribValue;
179     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_CONDITION_KHR, &attribValue));
180     EXPECT_EQ(attribValue, EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR);
181 
182     attribValue = kSentinelAttribValue;
183     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &attribValue));
184 
185     // Hack around EXPECT_* not having an "either this or that" variant:
186     if (attribValue != EGL_SIGNALED_KHR)
187     {
188         EXPECT_EQ(attribValue, EGL_UNSIGNALED_KHR);
189     }
190 
191     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
192 }
193 
194 // Test that basic usage works and doesn't generate errors or crash
TEST_P(EGLSyncTest,BasicOperations)195 TEST_P(EGLSyncTest, BasicOperations)
196 {
197     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
198 
199     EGLDisplay display = getEGLWindow()->getDisplay();
200 
201     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
202     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
203 
204     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
205 
206     glClear(GL_COLOR_BUFFER_BIT);
207     EXPECT_EGL_TRUE(eglWaitSyncKHR(display, sync, 0));
208 
209     glFlush();
210 
211     EGLint value           = 0;
212     unsigned int loopCount = 0;
213 
214     // Use 'loopCount' to make sure the test doesn't get stuck in an infinite loop
215     while (value != EGL_SIGNALED_KHR && loopCount <= 1000000)
216     {
217         loopCount++;
218         EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &value));
219     }
220 
221     ASSERT_EQ(value, EGL_SIGNALED_KHR);
222 
223     for (size_t i = 0; i < 20; i++)
224     {
225         glClear(GL_COLOR_BUFFER_BIT);
226         EXPECT_EQ(
227             EGL_CONDITION_SATISFIED_KHR,
228             eglClientWaitSyncKHR(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR));
229         EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &value));
230         EXPECT_EQ(value, EGL_SIGNALED_KHR);
231     }
232 
233     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
234 }
235 
236 // Test eglWaitNative api
TEST_P(EGLSyncTest,WaitNative)237 TEST_P(EGLSyncTest, WaitNative)
238 {
239     // Clear to red color
240     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
241 
242     glClear(GL_COLOR_BUFFER_BIT);
243     EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));
244     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
245 }
246 
247 ANGLE_INSTANTIATE_TEST(EGLSyncTest,
248                        ES2_D3D9(),
249                        ES2_D3D11(),
250                        ES3_D3D11(),
251                        ES2_OPENGL(),
252                        ES3_OPENGL(),
253                        ES2_OPENGLES(),
254                        ES3_OPENGLES(),
255                        ES2_VULKAN(),
256                        ES3_VULKAN());
257