xref: /aosp_15_r20/external/angle/src/tests/egl_tests/EGLSyncTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // EGLSyncTest.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //   Tests of EGL_KHR_fence_sync and EGL_KHR_wait_sync extensions.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include <gtest/gtest.h>
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/angle_test_configs.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "util/EGLWindow.h"
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker class EGLSyncTest : public ANGLETest<>
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker   protected:
hasFenceSyncExtension() const21*8975f5c5SAndroid Build Coastguard Worker     bool hasFenceSyncExtension() const
22*8975f5c5SAndroid Build Coastguard Worker     {
23*8975f5c5SAndroid Build Coastguard Worker         return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_fence_sync");
24*8975f5c5SAndroid Build Coastguard Worker     }
hasWaitSyncExtension() const25*8975f5c5SAndroid Build Coastguard Worker     bool hasWaitSyncExtension() const
26*8975f5c5SAndroid Build Coastguard Worker     {
27*8975f5c5SAndroid Build Coastguard Worker         return hasFenceSyncExtension() &&
28*8975f5c5SAndroid Build Coastguard Worker                IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_wait_sync");
29*8975f5c5SAndroid Build Coastguard Worker     }
hasGLSyncExtension() const30*8975f5c5SAndroid Build Coastguard Worker     bool hasGLSyncExtension() const { return IsGLExtensionEnabled("GL_OES_EGL_sync"); }
31*8975f5c5SAndroid Build Coastguard Worker 
hasAndroidNativeFenceSyncExtension() const32*8975f5c5SAndroid Build Coastguard Worker     bool hasAndroidNativeFenceSyncExtension() const
33*8975f5c5SAndroid Build Coastguard Worker     {
34*8975f5c5SAndroid Build Coastguard Worker         return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
35*8975f5c5SAndroid Build Coastguard Worker                                             "EGL_ANDROID_native_fence_sync");
36*8975f5c5SAndroid Build Coastguard Worker     }
37*8975f5c5SAndroid Build Coastguard Worker };
38*8975f5c5SAndroid Build Coastguard Worker 
39*8975f5c5SAndroid Build Coastguard Worker // Test error cases for all EGL_KHR_fence_sync functions
TEST_P(EGLSyncTest,FenceSyncErrors)40*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, FenceSyncErrors)
41*8975f5c5SAndroid Build Coastguard Worker {
42*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
43*8975f5c5SAndroid Build Coastguard Worker 
44*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker     // If the client API doesn't have the necessary extension, test that sync creation fails and
47*8975f5c5SAndroid Build Coastguard Worker     // ignore the rest of the tests.
48*8975f5c5SAndroid Build Coastguard Worker     if (!hasGLSyncExtension())
49*8975f5c5SAndroid Build Coastguard Worker     {
50*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr));
51*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_ERROR(EGL_BAD_MATCH);
52*8975f5c5SAndroid Build Coastguard Worker     }
53*8975f5c5SAndroid Build Coastguard Worker 
54*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasGLSyncExtension());
55*8975f5c5SAndroid Build Coastguard Worker 
56*8975f5c5SAndroid Build Coastguard Worker     EGLContext context     = eglGetCurrentContext();
57*8975f5c5SAndroid Build Coastguard Worker     EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);
58*8975f5c5SAndroid Build Coastguard Worker     EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);
59*8975f5c5SAndroid Build Coastguard Worker 
60*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(context, EGL_NO_CONTEXT);
61*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(drawSurface, EGL_NO_SURFACE);
62*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(readSurface, EGL_NO_SURFACE);
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker     // CreateSync with no attribute shouldn't cause an error
65*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
66*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
69*8975f5c5SAndroid Build Coastguard Worker 
70*8975f5c5SAndroid Build Coastguard Worker     // CreateSync with empty attribute shouldn't cause an error
71*8975f5c5SAndroid Build Coastguard Worker     const EGLint emptyAttributes[] = {EGL_NONE};
72*8975f5c5SAndroid Build Coastguard Worker     sync                           = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, emptyAttributes);
73*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker     // DestroySync generates BAD_PARAMETER if the sync is not valid
76*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglDestroySyncKHR(display, reinterpret_cast<EGLSyncKHR>(20)));
77*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
78*8975f5c5SAndroid Build Coastguard Worker 
79*8975f5c5SAndroid Build Coastguard Worker     // CreateSync generates BAD_DISPLAY if display is not valid
80*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(EGL_NO_DISPLAY, EGL_SYNC_FENCE_KHR, nullptr));
81*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
82*8975f5c5SAndroid Build Coastguard Worker 
83*8975f5c5SAndroid Build Coastguard Worker     // CreateSync generates BAD_ATTRIBUTE if attribute is neither nullptr nor empty.
84*8975f5c5SAndroid Build Coastguard Worker     const EGLint nonEmptyAttributes[] = {
85*8975f5c5SAndroid Build Coastguard Worker         EGL_CL_EVENT_HANDLE,
86*8975f5c5SAndroid Build Coastguard Worker         0,
87*8975f5c5SAndroid Build Coastguard Worker         EGL_NONE,
88*8975f5c5SAndroid Build Coastguard Worker     };
89*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nonEmptyAttributes));
90*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
91*8975f5c5SAndroid Build Coastguard Worker 
92*8975f5c5SAndroid Build Coastguard Worker     // CreateSync generates BAD_ATTRIBUTE if type is not valid
93*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, 0, nullptr));
94*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
95*8975f5c5SAndroid Build Coastguard Worker 
96*8975f5c5SAndroid Build Coastguard Worker     // CreateSync generates BAD_MATCH if no context is current
97*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
98*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr));
99*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_MATCH);
100*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, drawSurface, readSurface, context);
101*8975f5c5SAndroid Build Coastguard Worker 
102*8975f5c5SAndroid Build Coastguard Worker     // ClientWaitSync generates EGL_BAD_PARAMETER if the sync object is not valid
103*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglClientWaitSyncKHR(display, reinterpret_cast<EGLSyncKHR>(30), 0, 0));
104*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker     // GetSyncAttrib generates EGL_BAD_PARAMETER if the sync object is not valid, and value is not
107*8975f5c5SAndroid Build Coastguard Worker     // modified
108*8975f5c5SAndroid Build Coastguard Worker     constexpr EGLint kSentinelAttribValue = 123456789;
109*8975f5c5SAndroid Build Coastguard Worker     EGLint attribValue                    = kSentinelAttribValue;
110*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglGetSyncAttribKHR(display, reinterpret_cast<EGLSyncKHR>(40),
111*8975f5c5SAndroid Build Coastguard Worker                                          EGL_SYNC_TYPE_KHR, &attribValue));
112*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
113*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(attribValue, kSentinelAttribValue);
114*8975f5c5SAndroid Build Coastguard Worker 
115*8975f5c5SAndroid Build Coastguard Worker     // GetSyncAttrib generates EGL_BAD_ATTRIBUTE if the attribute is not valid, and value is not
116*8975f5c5SAndroid Build Coastguard Worker     // modified
117*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglGetSyncAttribKHR(display, sync, EGL_CL_EVENT_HANDLE, &attribValue));
118*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
119*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(attribValue, kSentinelAttribValue);
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker     // GetSyncAttrib generates EGL_BAD_MATCH if the attribute is valid for sync, but not the
122*8975f5c5SAndroid Build Coastguard Worker     // particular sync type. We don't have such a case at the moment.
123*8975f5c5SAndroid Build Coastguard Worker 
124*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
125*8975f5c5SAndroid Build Coastguard Worker }
126*8975f5c5SAndroid Build Coastguard Worker 
127*8975f5c5SAndroid Build Coastguard Worker // Test error cases for all EGL_KHR_wait_sync functions
TEST_P(EGLSyncTest,WaitSyncErrors)128*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, WaitSyncErrors)
129*8975f5c5SAndroid Build Coastguard Worker {
130*8975f5c5SAndroid Build Coastguard Worker     // The client API that shows support for eglWaitSyncKHR is the same as the one required for
131*8975f5c5SAndroid Build Coastguard Worker     // eglCreateSyncKHR.  As such, there is no way to create a sync and not be able to wait on it.
132*8975f5c5SAndroid Build Coastguard Worker     // This would have created an EGL_BAD_MATCH error.
133*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
134*8975f5c5SAndroid Build Coastguard Worker 
135*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display     = getEGLWindow()->getDisplay();
136*8975f5c5SAndroid Build Coastguard Worker     EGLContext context     = eglGetCurrentContext();
137*8975f5c5SAndroid Build Coastguard Worker     EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);
138*8975f5c5SAndroid Build Coastguard Worker     EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);
139*8975f5c5SAndroid Build Coastguard Worker 
140*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(context, EGL_NO_CONTEXT);
141*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(drawSurface, EGL_NO_SURFACE);
142*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(readSurface, EGL_NO_SURFACE);
143*8975f5c5SAndroid Build Coastguard Worker 
144*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
145*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
146*8975f5c5SAndroid Build Coastguard Worker 
147*8975f5c5SAndroid Build Coastguard Worker     // WaitSync generates BAD_MATCH if no context is current
148*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
149*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglWaitSyncKHR(display, sync, 0));
150*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_MATCH);
151*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, drawSurface, readSurface, context);
152*8975f5c5SAndroid Build Coastguard Worker 
153*8975f5c5SAndroid Build Coastguard Worker     // WaitSync generates BAD_PARAMETER if the sync is not valid
154*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglWaitSyncKHR(display, reinterpret_cast<EGLSyncKHR>(20), 0));
155*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker     // WaitSync generates BAD_PARAMETER if flags is non-zero
158*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_FALSE(eglWaitSyncKHR(display, sync, 1));
159*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
160*8975f5c5SAndroid Build Coastguard Worker 
161*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
162*8975f5c5SAndroid Build Coastguard Worker }
163*8975f5c5SAndroid Build Coastguard Worker 
164*8975f5c5SAndroid Build Coastguard Worker // Test usage of eglGetSyncAttribKHR
TEST_P(EGLSyncTest,GetSyncAttrib)165*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, GetSyncAttrib)
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
170*8975f5c5SAndroid Build Coastguard Worker 
171*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
172*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
173*8975f5c5SAndroid Build Coastguard Worker 
174*8975f5c5SAndroid Build Coastguard Worker     // Fence sync attributes are:
175*8975f5c5SAndroid Build Coastguard Worker     //
176*8975f5c5SAndroid Build Coastguard Worker     // EGL_SYNC_TYPE_KHR: EGL_SYNC_FENCE_KHR
177*8975f5c5SAndroid Build Coastguard Worker     // EGL_SYNC_STATUS_KHR: EGL_UNSIGNALED_KHR or EGL_SIGNALED_KHR
178*8975f5c5SAndroid Build Coastguard Worker     // EGL_SYNC_CONDITION_KHR: EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
179*8975f5c5SAndroid Build Coastguard Worker 
180*8975f5c5SAndroid Build Coastguard Worker     constexpr EGLint kSentinelAttribValue = 123456789;
181*8975f5c5SAndroid Build Coastguard Worker     EGLint attribValue                    = kSentinelAttribValue;
182*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_TYPE_KHR, &attribValue));
183*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(attribValue, EGL_SYNC_FENCE_KHR);
184*8975f5c5SAndroid Build Coastguard Worker 
185*8975f5c5SAndroid Build Coastguard Worker     attribValue = kSentinelAttribValue;
186*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_CONDITION_KHR, &attribValue));
187*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(attribValue, EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR);
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker     attribValue = kSentinelAttribValue;
190*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &attribValue));
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker     // Hack around EXPECT_* not having an "either this or that" variant:
193*8975f5c5SAndroid Build Coastguard Worker     if (attribValue != EGL_SIGNALED_KHR)
194*8975f5c5SAndroid Build Coastguard Worker     {
195*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(attribValue, EGL_UNSIGNALED_KHR);
196*8975f5c5SAndroid Build Coastguard Worker     }
197*8975f5c5SAndroid Build Coastguard Worker 
198*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker 
201*8975f5c5SAndroid Build Coastguard Worker // Test that basic usage works and doesn't generate errors or crash
TEST_P(EGLSyncTest,BasicOperations)202*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, BasicOperations)
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
207*8975f5c5SAndroid Build Coastguard Worker 
208*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
209*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
210*8975f5c5SAndroid Build Coastguard Worker 
211*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
214*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitSyncKHR(display, sync, 0));
215*8975f5c5SAndroid Build Coastguard Worker 
216*8975f5c5SAndroid Build Coastguard Worker     glFlush();
217*8975f5c5SAndroid Build Coastguard Worker 
218*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     // Don't wait forever to make sure the test terminates
221*8975f5c5SAndroid Build Coastguard Worker     constexpr GLuint64 kTimeout = 1'000'000'000;  // 1 second
222*8975f5c5SAndroid Build Coastguard Worker     EGLint value                = 0;
223*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR,
224*8975f5c5SAndroid Build Coastguard Worker               eglClientWaitSyncKHR(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, kTimeout));
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < 20; i++)
227*8975f5c5SAndroid Build Coastguard Worker     {
228*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
229*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(
230*8975f5c5SAndroid Build Coastguard Worker             EGL_CONDITION_SATISFIED_KHR,
231*8975f5c5SAndroid Build Coastguard Worker             eglClientWaitSyncKHR(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR));
232*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &value));
233*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(value, EGL_SIGNALED_KHR);
234*8975f5c5SAndroid Build Coastguard Worker     }
235*8975f5c5SAndroid Build Coastguard Worker 
236*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));
237*8975f5c5SAndroid Build Coastguard Worker }
238*8975f5c5SAndroid Build Coastguard Worker 
239*8975f5c5SAndroid Build Coastguard Worker // Test that eglClientWaitSync* APIs work.
TEST_P(EGLSyncTest,EglClientWaitSync)240*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, EglClientWaitSync)
241*8975f5c5SAndroid Build Coastguard Worker {
242*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
243*8975f5c5SAndroid Build Coastguard Worker 
244*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
245*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
246*8975f5c5SAndroid Build Coastguard Worker 
247*8975f5c5SAndroid Build Coastguard Worker     // Test eglClientWaitSyncKHR
248*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < 5; i++)
249*8975f5c5SAndroid Build Coastguard Worker     {
250*8975f5c5SAndroid Build Coastguard Worker         glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
251*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
252*8975f5c5SAndroid Build Coastguard Worker         drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
253*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
254*8975f5c5SAndroid Build Coastguard Worker 
255*8975f5c5SAndroid Build Coastguard Worker         // Don't wait forever to make sure the test terminates
256*8975f5c5SAndroid Build Coastguard Worker         constexpr GLuint64 kTimeout = 1'000'000'000;  // 1 second
257*8975f5c5SAndroid Build Coastguard Worker         EGLSyncKHR clientWaitSync   = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
258*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(clientWaitSync, EGL_NO_SYNC_KHR);
259*8975f5c5SAndroid Build Coastguard Worker 
260*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR,
261*8975f5c5SAndroid Build Coastguard Worker                   eglClientWaitSyncKHR(display, clientWaitSync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
262*8975f5c5SAndroid Build Coastguard Worker                                        kTimeout));
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroySyncKHR(display, clientWaitSync));
265*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EGL_SUCCESS();
266*8975f5c5SAndroid Build Coastguard Worker     }
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker     // Test eglClientWaitSync
269*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < 5; i++)
270*8975f5c5SAndroid Build Coastguard Worker     {
271*8975f5c5SAndroid Build Coastguard Worker         glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
272*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
273*8975f5c5SAndroid Build Coastguard Worker         drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
274*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
275*8975f5c5SAndroid Build Coastguard Worker 
276*8975f5c5SAndroid Build Coastguard Worker         // Don't wait forever to make sure the test terminates
277*8975f5c5SAndroid Build Coastguard Worker         constexpr GLuint64 kTimeout = 1'000'000'000;  // 1 second
278*8975f5c5SAndroid Build Coastguard Worker         EGLSyncKHR clientWaitSync   = eglCreateSync(display, EGL_SYNC_FENCE, nullptr);
279*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(clientWaitSync, EGL_NO_SYNC);
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EQ(
282*8975f5c5SAndroid Build Coastguard Worker             EGL_CONDITION_SATISFIED,
283*8975f5c5SAndroid Build Coastguard Worker             eglClientWaitSync(display, clientWaitSync, EGL_SYNC_FLUSH_COMMANDS_BIT, kTimeout));
284*8975f5c5SAndroid Build Coastguard Worker 
285*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroySync(display, clientWaitSync));
286*8975f5c5SAndroid Build Coastguard Worker         ASSERT_EGL_SUCCESS();
287*8975f5c5SAndroid Build Coastguard Worker     }
288*8975f5c5SAndroid Build Coastguard Worker }
289*8975f5c5SAndroid Build Coastguard Worker 
290*8975f5c5SAndroid Build Coastguard Worker // Test eglWaitClient api
TEST_P(EGLSyncTest,WaitClient)291*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, WaitClient)
292*8975f5c5SAndroid Build Coastguard Worker {
293*8975f5c5SAndroid Build Coastguard Worker     // Clear to red color
294*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
295*8975f5c5SAndroid Build Coastguard Worker 
296*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
297*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitClient());
298*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
301*8975f5c5SAndroid Build Coastguard Worker     EGLContext context = getEGLWindow()->getContext();
302*8975f5c5SAndroid Build Coastguard Worker     EGLSurface surface = getEGLWindow()->getSurface();
303*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
304*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitClient());
305*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, surface, surface, context);
306*8975f5c5SAndroid Build Coastguard Worker }
307*8975f5c5SAndroid Build Coastguard Worker 
308*8975f5c5SAndroid Build Coastguard Worker // Test eglWaitGL api
TEST_P(EGLSyncTest,WaitGL)309*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, WaitGL)
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker     // Clear to red color
312*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
313*8975f5c5SAndroid Build Coastguard Worker 
314*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
315*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitGL());
316*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
317*8975f5c5SAndroid Build Coastguard Worker 
318*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
319*8975f5c5SAndroid Build Coastguard Worker     EGLContext context = getEGLWindow()->getContext();
320*8975f5c5SAndroid Build Coastguard Worker     EGLSurface surface = getEGLWindow()->getSurface();
321*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
322*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitGL());
323*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, surface, surface, context);
324*8975f5c5SAndroid Build Coastguard Worker }
325*8975f5c5SAndroid Build Coastguard Worker 
326*8975f5c5SAndroid Build Coastguard Worker // Test eglWaitNative api
TEST_P(EGLSyncTest,WaitNative)327*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, WaitNative)
328*8975f5c5SAndroid Build Coastguard Worker {
329*8975f5c5SAndroid Build Coastguard Worker     // Clear to red color
330*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
331*8975f5c5SAndroid Build Coastguard Worker 
332*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
333*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));
334*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
335*8975f5c5SAndroid Build Coastguard Worker 
336*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
337*8975f5c5SAndroid Build Coastguard Worker     EGLContext context = getEGLWindow()->getContext();
338*8975f5c5SAndroid Build Coastguard Worker     EGLSurface surface = getEGLWindow()->getSurface();
339*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
340*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));
341*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, surface, surface, context);
342*8975f5c5SAndroid Build Coastguard Worker }
343*8975f5c5SAndroid Build Coastguard Worker 
344*8975f5c5SAndroid Build Coastguard Worker // Verify eglDupNativeFence for EGL_ANDROID_native_fence_sync
TEST_P(EGLSyncTest,AndroidNativeFence_DupNativeFenceFD)345*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, AndroidNativeFence_DupNativeFenceFD)
346*8975f5c5SAndroid Build Coastguard Worker {
347*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
348*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
349*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
350*8975f5c5SAndroid Build Coastguard Worker 
351*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
352*8975f5c5SAndroid Build Coastguard Worker 
353*8975f5c5SAndroid Build Coastguard Worker     // We can ClientWait on this
354*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncWithGeneratedFD =
355*8975f5c5SAndroid Build Coastguard Worker         eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
356*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);
357*8975f5c5SAndroid Build Coastguard Worker 
358*8975f5c5SAndroid Build Coastguard Worker     int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD);
359*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_SUCCESS();
360*8975f5c5SAndroid Build Coastguard Worker 
361*8975f5c5SAndroid Build Coastguard Worker     // Clean up created objects.
362*8975f5c5SAndroid Build Coastguard Worker     if (fd != EGL_NO_NATIVE_FENCE_FD_ANDROID)
363*8975f5c5SAndroid Build Coastguard Worker     {
364*8975f5c5SAndroid Build Coastguard Worker         close(fd);
365*8975f5c5SAndroid Build Coastguard Worker     }
366*8975f5c5SAndroid Build Coastguard Worker 
367*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));
368*8975f5c5SAndroid Build Coastguard Worker }
369*8975f5c5SAndroid Build Coastguard Worker 
370*8975f5c5SAndroid Build Coastguard Worker // Verify CreateSync and ClientWait for EGL_ANDROID_native_fence_sync
TEST_P(EGLSyncTest,AndroidNativeFence_ClientWait)371*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, AndroidNativeFence_ClientWait)
372*8975f5c5SAndroid Build Coastguard Worker {
373*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
374*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
375*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
376*8975f5c5SAndroid Build Coastguard Worker 
377*8975f5c5SAndroid Build Coastguard Worker     EGLint value       = 0;
378*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
379*8975f5c5SAndroid Build Coastguard Worker 
380*8975f5c5SAndroid Build Coastguard Worker     // We can ClientWait on this
381*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncWithGeneratedFD =
382*8975f5c5SAndroid Build Coastguard Worker         eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
383*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);
384*8975f5c5SAndroid Build Coastguard Worker 
385*8975f5c5SAndroid Build Coastguard Worker     // Create work to do
386*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
387*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
388*8975f5c5SAndroid Build Coastguard Worker     glFlush();
389*8975f5c5SAndroid Build Coastguard Worker 
390*8975f5c5SAndroid Build Coastguard Worker     // Wait for draw to complete
391*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_CONDITION_SATISFIED,
392*8975f5c5SAndroid Build Coastguard Worker               eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
393*8975f5c5SAndroid Build Coastguard Worker                                    1'000'000'000));
394*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));
395*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(value, EGL_SIGNALED_KHR);
396*8975f5c5SAndroid Build Coastguard Worker 
397*8975f5c5SAndroid Build Coastguard Worker     // Clean up created objects.
398*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));
399*8975f5c5SAndroid Build Coastguard Worker }
400*8975f5c5SAndroid Build Coastguard Worker 
401*8975f5c5SAndroid Build Coastguard Worker // Verify WaitSync with EGL_ANDROID_native_fence_sync
402*8975f5c5SAndroid Build Coastguard Worker // Simulate passing FDs across processes by passing across Contexts.
TEST_P(EGLSyncTest,AndroidNativeFence_WaitSync)403*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)
404*8975f5c5SAndroid Build Coastguard Worker {
405*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
406*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
407*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
408*8975f5c5SAndroid Build Coastguard Worker 
409*8975f5c5SAndroid Build Coastguard Worker     EGLint value       = 0;
410*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
411*8975f5c5SAndroid Build Coastguard Worker     EGLSurface surface = getEGLWindow()->getSurface();
412*8975f5c5SAndroid Build Coastguard Worker 
413*8975f5c5SAndroid Build Coastguard Worker     /*- First Context ------------------------*/
414*8975f5c5SAndroid Build Coastguard Worker 
415*8975f5c5SAndroid Build Coastguard Worker     // We can ClientWait on this
416*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncWithGeneratedFD =
417*8975f5c5SAndroid Build Coastguard Worker         eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
418*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);
419*8975f5c5SAndroid Build Coastguard Worker 
420*8975f5c5SAndroid Build Coastguard Worker     int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD);
421*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_SUCCESS();  // Can return -1 (when signaled) or valid FD.
422*8975f5c5SAndroid Build Coastguard Worker 
423*8975f5c5SAndroid Build Coastguard Worker     // Create work to do
424*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
425*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
426*8975f5c5SAndroid Build Coastguard Worker     glFlush();
427*8975f5c5SAndroid Build Coastguard Worker 
428*8975f5c5SAndroid Build Coastguard Worker     /*- Second Context ------------------------*/
429*8975f5c5SAndroid Build Coastguard Worker     if (fd > EGL_NO_NATIVE_FENCE_FD_ANDROID)
430*8975f5c5SAndroid Build Coastguard Worker     {
431*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
432*8975f5c5SAndroid Build Coastguard Worker 
433*8975f5c5SAndroid Build Coastguard Worker         EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT, nullptr);
434*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2));
435*8975f5c5SAndroid Build Coastguard Worker 
436*8975f5c5SAndroid Build Coastguard Worker         // We can eglWaitSync on this - import FD from first sync.
437*8975f5c5SAndroid Build Coastguard Worker         EGLint syncAttribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, (EGLint)fd, EGL_NONE};
438*8975f5c5SAndroid Build Coastguard Worker         EGLSyncKHR syncWithDupFD =
439*8975f5c5SAndroid Build Coastguard Worker             eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, syncAttribs);
440*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(syncWithDupFD, EGL_NO_SYNC_KHR);
441*8975f5c5SAndroid Build Coastguard Worker 
442*8975f5c5SAndroid Build Coastguard Worker         // Second draw waits for first to complete. May already be signaled - ignore error.
443*8975f5c5SAndroid Build Coastguard Worker         if (eglWaitSyncKHR(display, syncWithDupFD, 0) == EGL_TRUE)
444*8975f5c5SAndroid Build Coastguard Worker         {
445*8975f5c5SAndroid Build Coastguard Worker             // Create work to do
446*8975f5c5SAndroid Build Coastguard Worker             glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
447*8975f5c5SAndroid Build Coastguard Worker             glClear(GL_COLOR_BUFFER_BIT);
448*8975f5c5SAndroid Build Coastguard Worker             glFlush();
449*8975f5c5SAndroid Build Coastguard Worker         }
450*8975f5c5SAndroid Build Coastguard Worker 
451*8975f5c5SAndroid Build Coastguard Worker         // Wait for second draw to complete
452*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(EGL_CONDITION_SATISFIED,
453*8975f5c5SAndroid Build Coastguard Worker                   eglClientWaitSyncKHR(display, syncWithDupFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
454*8975f5c5SAndroid Build Coastguard Worker                                        1000000000));
455*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithDupFD, EGL_SYNC_STATUS_KHR, &value));
456*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(value, EGL_SIGNALED_KHR);
457*8975f5c5SAndroid Build Coastguard Worker 
458*8975f5c5SAndroid Build Coastguard Worker         // Reset to default context and surface.
459*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
460*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, getEGLWindow()->getContext()));
461*8975f5c5SAndroid Build Coastguard Worker 
462*8975f5c5SAndroid Build Coastguard Worker         // Clean up created objects.
463*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithDupFD));
464*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroyContext(display, context2));
465*8975f5c5SAndroid Build Coastguard Worker     }
466*8975f5c5SAndroid Build Coastguard Worker 
467*8975f5c5SAndroid Build Coastguard Worker     // Wait for first draw to complete
468*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_CONDITION_SATISFIED,
469*8975f5c5SAndroid Build Coastguard Worker               eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
470*8975f5c5SAndroid Build Coastguard Worker                                    1000000000));
471*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));
472*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(value, EGL_SIGNALED_KHR);
473*8975f5c5SAndroid Build Coastguard Worker 
474*8975f5c5SAndroid Build Coastguard Worker     // Clean up created objects.
475*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker 
478*8975f5c5SAndroid Build Coastguard Worker // Verify EGL_ANDROID_native_fence_sync
479*8975f5c5SAndroid Build Coastguard Worker // Simulate passing FDs across processes by passing across Contexts.
TEST_P(EGLSyncTest,AndroidNativeFence_withFences)480*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, AndroidNativeFence_withFences)
481*8975f5c5SAndroid Build Coastguard Worker {
482*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
483*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
484*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
485*8975f5c5SAndroid Build Coastguard Worker 
486*8975f5c5SAndroid Build Coastguard Worker     EGLint value       = 0;
487*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
488*8975f5c5SAndroid Build Coastguard Worker     EGLSurface surface = getEGLWindow()->getSurface();
489*8975f5c5SAndroid Build Coastguard Worker 
490*8975f5c5SAndroid Build Coastguard Worker     /*- First Context ------------------------*/
491*8975f5c5SAndroid Build Coastguard Worker 
492*8975f5c5SAndroid Build Coastguard Worker     // Extra fence syncs to ensure that Fence and Android Native fences work together
493*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncFence1 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
494*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncFence1, EGL_NO_SYNC_KHR);
495*8975f5c5SAndroid Build Coastguard Worker 
496*8975f5c5SAndroid Build Coastguard Worker     // We can ClientWait on this
497*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncWithGeneratedFD =
498*8975f5c5SAndroid Build Coastguard Worker         eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
499*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);
500*8975f5c5SAndroid Build Coastguard Worker 
501*8975f5c5SAndroid Build Coastguard Worker     int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD);
502*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_SUCCESS();  // Can return -1 (when signaled) or valid FD.
503*8975f5c5SAndroid Build Coastguard Worker 
504*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncFence2 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
505*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncFence2, EGL_NO_SYNC_KHR);
506*8975f5c5SAndroid Build Coastguard Worker 
507*8975f5c5SAndroid Build Coastguard Worker     // Create work to do
508*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
509*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
510*8975f5c5SAndroid Build Coastguard Worker     glFlush();
511*8975f5c5SAndroid Build Coastguard Worker 
512*8975f5c5SAndroid Build Coastguard Worker     /*- Second Context ------------------------*/
513*8975f5c5SAndroid Build Coastguard Worker     if (fd > EGL_NO_NATIVE_FENCE_FD_ANDROID)
514*8975f5c5SAndroid Build Coastguard Worker     {
515*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
516*8975f5c5SAndroid Build Coastguard Worker 
517*8975f5c5SAndroid Build Coastguard Worker         EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT, nullptr);
518*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2));
519*8975f5c5SAndroid Build Coastguard Worker 
520*8975f5c5SAndroid Build Coastguard Worker         // check that Fence and Android fences work together
521*8975f5c5SAndroid Build Coastguard Worker         EGLSyncKHR syncFence3 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
522*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(syncFence3, EGL_NO_SYNC_KHR);
523*8975f5c5SAndroid Build Coastguard Worker 
524*8975f5c5SAndroid Build Coastguard Worker         // We can eglWaitSync on this
525*8975f5c5SAndroid Build Coastguard Worker         EGLint syncAttribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, (EGLint)fd, EGL_NONE};
526*8975f5c5SAndroid Build Coastguard Worker         EGLSyncKHR syncWithDupFD =
527*8975f5c5SAndroid Build Coastguard Worker             eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, syncAttribs);
528*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(syncWithDupFD, EGL_NO_SYNC_KHR);
529*8975f5c5SAndroid Build Coastguard Worker 
530*8975f5c5SAndroid Build Coastguard Worker         EGLSyncKHR syncFence4 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
531*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(syncFence4, EGL_NO_SYNC_KHR);
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker         // Second draw waits for first to complete. May already be signaled - ignore error.
534*8975f5c5SAndroid Build Coastguard Worker         if (eglWaitSyncKHR(display, syncWithDupFD, 0) == EGL_TRUE)
535*8975f5c5SAndroid Build Coastguard Worker         {
536*8975f5c5SAndroid Build Coastguard Worker             // Create work to do
537*8975f5c5SAndroid Build Coastguard Worker             glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
538*8975f5c5SAndroid Build Coastguard Worker             glClear(GL_COLOR_BUFFER_BIT);
539*8975f5c5SAndroid Build Coastguard Worker             glFlush();
540*8975f5c5SAndroid Build Coastguard Worker         }
541*8975f5c5SAndroid Build Coastguard Worker 
542*8975f5c5SAndroid Build Coastguard Worker         // Wait for second draw to complete
543*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(EGL_CONDITION_SATISFIED,
544*8975f5c5SAndroid Build Coastguard Worker                   eglClientWaitSyncKHR(display, syncWithDupFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
545*8975f5c5SAndroid Build Coastguard Worker                                        1000000000));
546*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithDupFD, EGL_SYNC_STATUS_KHR, &value));
547*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(value, EGL_SIGNALED_KHR);
548*8975f5c5SAndroid Build Coastguard Worker 
549*8975f5c5SAndroid Build Coastguard Worker         // Reset to default context and surface.
550*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
551*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, getEGLWindow()->getContext()));
552*8975f5c5SAndroid Build Coastguard Worker 
553*8975f5c5SAndroid Build Coastguard Worker         // Clean up created objects.
554*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence3));
555*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence4));
556*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithDupFD));
557*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EGL_TRUE(eglDestroyContext(display, context2));
558*8975f5c5SAndroid Build Coastguard Worker     }
559*8975f5c5SAndroid Build Coastguard Worker 
560*8975f5c5SAndroid Build Coastguard Worker     // Wait for first draw to complete
561*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_CONDITION_SATISFIED,
562*8975f5c5SAndroid Build Coastguard Worker               eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
563*8975f5c5SAndroid Build Coastguard Worker                                    1000000000));
564*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));
565*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(value, EGL_SIGNALED_KHR);
566*8975f5c5SAndroid Build Coastguard Worker 
567*8975f5c5SAndroid Build Coastguard Worker     // Clean up created objects.
568*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence1));
569*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence2));
570*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));
571*8975f5c5SAndroid Build Coastguard Worker }
572*8975f5c5SAndroid Build Coastguard Worker 
573*8975f5c5SAndroid Build Coastguard Worker // Verify that VkSemaphore is not destroyed before used for waiting
TEST_P(EGLSyncTest,AndroidNativeFence_VkSemaphoreDestroyBug)574*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, AndroidNativeFence_VkSemaphoreDestroyBug)
575*8975f5c5SAndroid Build Coastguard Worker {
576*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
577*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
578*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
579*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
582*8975f5c5SAndroid Build Coastguard Worker 
583*8975f5c5SAndroid Build Coastguard Worker     glFinish();  // Ensure no pending commands
584*8975f5c5SAndroid Build Coastguard Worker 
585*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncWithGeneratedFD =
586*8975f5c5SAndroid Build Coastguard Worker         eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
587*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);
588*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglWaitSyncKHR(display, syncWithGeneratedFD, 0));
589*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));
590*8975f5c5SAndroid Build Coastguard Worker     glFinish();  // May destroy VkSemaphore if bug is present.
591*8975f5c5SAndroid Build Coastguard Worker 
592*8975f5c5SAndroid Build Coastguard Worker     // Create work to do
593*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
594*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
595*8975f5c5SAndroid Build Coastguard Worker     glFinish();  // Will submit destroyed Semaphores.
596*8975f5c5SAndroid Build Coastguard Worker }
597*8975f5c5SAndroid Build Coastguard Worker 
598*8975f5c5SAndroid Build Coastguard Worker // Verify that no VVL errors are generated when External Fence Handle is used to track submissions
TEST_P(EGLSyncTest,AndroidNativeFence_ExternalFenceWaitVVLBug)599*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, AndroidNativeFence_ExternalFenceWaitVVLBug)
600*8975f5c5SAndroid Build Coastguard Worker {
601*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
602*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());
603*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
604*8975f5c5SAndroid Build Coastguard Worker 
605*8975f5c5SAndroid Build Coastguard Worker     EGLint value       = 0;
606*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
607*8975f5c5SAndroid Build Coastguard Worker 
608*8975f5c5SAndroid Build Coastguard Worker     // Create work to do
609*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
610*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
611*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
612*8975f5c5SAndroid Build Coastguard Worker 
613*8975f5c5SAndroid Build Coastguard Worker     // We can ClientWait on this
614*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR syncWithGeneratedFD =
615*8975f5c5SAndroid Build Coastguard Worker         eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
616*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);
617*8975f5c5SAndroid Build Coastguard Worker 
618*8975f5c5SAndroid Build Coastguard Worker     // Wait for draw to complete
619*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_CONDITION_SATISFIED,
620*8975f5c5SAndroid Build Coastguard Worker               eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
621*8975f5c5SAndroid Build Coastguard Worker                                    1'000'000'000));
622*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));
623*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(value, EGL_SIGNALED_KHR);
624*8975f5c5SAndroid Build Coastguard Worker 
625*8975f5c5SAndroid Build Coastguard Worker     // Clean up created objects.
626*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));
627*8975f5c5SAndroid Build Coastguard Worker 
628*8975f5c5SAndroid Build Coastguard Worker     // Finish to cleanup internal garbage in the backend.
629*8975f5c5SAndroid Build Coastguard Worker     glFinish();
630*8975f5c5SAndroid Build Coastguard Worker }
631*8975f5c5SAndroid Build Coastguard Worker 
632*8975f5c5SAndroid Build Coastguard Worker // Test functionality of EGL_ANGLE_global_fence_sync.
TEST_P(EGLSyncTest,GlobalFenceSync)633*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, GlobalFenceSync)
634*8975f5c5SAndroid Build Coastguard Worker {
635*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
636*8975f5c5SAndroid Build Coastguard Worker 
637*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
638*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_global_fence_sync"));
639*8975f5c5SAndroid Build Coastguard Worker 
640*8975f5c5SAndroid Build Coastguard Worker     // Create a second context
641*8975f5c5SAndroid Build Coastguard Worker     EGLContext context1     = eglGetCurrentContext();
642*8975f5c5SAndroid Build Coastguard Worker     EGLSurface drawSurface1 = eglGetCurrentSurface(EGL_DRAW);
643*8975f5c5SAndroid Build Coastguard Worker     EGLSurface readSurface1 = eglGetCurrentSurface(EGL_READ);
644*8975f5c5SAndroid Build Coastguard Worker     EGLConfig config        = getEGLWindow()->getConfig();
645*8975f5c5SAndroid Build Coastguard Worker 
646*8975f5c5SAndroid Build Coastguard Worker     const EGLint contextAttribs[] = {
647*8975f5c5SAndroid Build Coastguard Worker         EGL_CONTEXT_CLIENT_VERSION, getEGLWindow()->getClientMajorVersion(),
648*8975f5c5SAndroid Build Coastguard Worker         EGL_CONTEXT_MINOR_VERSION_KHR, getEGLWindow()->getClientMinorVersion(), EGL_NONE};
649*8975f5c5SAndroid Build Coastguard Worker 
650*8975f5c5SAndroid Build Coastguard Worker     EGLContext context2 = eglCreateContext(display, config, context1, contextAttribs);
651*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(EGL_NO_CONTEXT, context2);
652*8975f5c5SAndroid Build Coastguard Worker 
653*8975f5c5SAndroid Build Coastguard Worker     const EGLint pbufferAttribs[] = {EGL_WIDTH, getWindowWidth(), EGL_HEIGHT, getWindowHeight(),
654*8975f5c5SAndroid Build Coastguard Worker                                      EGL_NONE};
655*8975f5c5SAndroid Build Coastguard Worker     EGLSurface drawSurface2       = eglCreatePbufferSurface(display, config, pbufferAttribs);
656*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(EGL_NO_SURFACE, drawSurface2);
657*8975f5c5SAndroid Build Coastguard Worker 
658*8975f5c5SAndroid Build Coastguard Worker     // Do an expensive draw in context 2
659*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, drawSurface2, drawSurface2, context2);
660*8975f5c5SAndroid Build Coastguard Worker 
661*8975f5c5SAndroid Build Coastguard Worker     constexpr char kCostlyVS[] = R"(attribute highp vec4 position;
662*8975f5c5SAndroid Build Coastguard Worker varying highp vec4 testPos;
663*8975f5c5SAndroid Build Coastguard Worker void main(void)
664*8975f5c5SAndroid Build Coastguard Worker {
665*8975f5c5SAndroid Build Coastguard Worker     testPos     = position;
666*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
667*8975f5c5SAndroid Build Coastguard Worker })";
668*8975f5c5SAndroid Build Coastguard Worker 
669*8975f5c5SAndroid Build Coastguard Worker     constexpr char kCostlyFS[] = R"(precision highp float;
670*8975f5c5SAndroid Build Coastguard Worker varying highp vec4 testPos;
671*8975f5c5SAndroid Build Coastguard Worker void main(void)
672*8975f5c5SAndroid Build Coastguard Worker {
673*8975f5c5SAndroid Build Coastguard Worker     vec4 test = testPos;
674*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 500; i++)
675*8975f5c5SAndroid Build Coastguard Worker     {
676*8975f5c5SAndroid Build Coastguard Worker         test = sqrt(test);
677*8975f5c5SAndroid Build Coastguard Worker     }
678*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = test;
679*8975f5c5SAndroid Build Coastguard Worker })";
680*8975f5c5SAndroid Build Coastguard Worker 
681*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(expensiveProgram, kCostlyVS, kCostlyFS);
682*8975f5c5SAndroid Build Coastguard Worker     drawQuad(expensiveProgram, "position", 0.0f);
683*8975f5c5SAndroid Build Coastguard Worker 
684*8975f5c5SAndroid Build Coastguard Worker     // Signal a fence sync for testing
685*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync2 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
686*8975f5c5SAndroid Build Coastguard Worker 
687*8975f5c5SAndroid Build Coastguard Worker     // Switch to context 1, and create a global fence sync
688*8975f5c5SAndroid Build Coastguard Worker     eglMakeCurrent(display, drawSurface1, readSurface1, context1);
689*8975f5c5SAndroid Build Coastguard Worker 
690*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync1 = eglCreateSyncKHR(display, EGL_SYNC_GLOBAL_FENCE_ANGLE, nullptr);
691*8975f5c5SAndroid Build Coastguard Worker 
692*8975f5c5SAndroid Build Coastguard Worker     // Wait for the global fence sync to finish.
693*8975f5c5SAndroid Build Coastguard Worker     constexpr GLuint64 kTimeout = 1'000'000'000;  // 1 second
694*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR, eglClientWaitSyncKHR(display, sync1, 0, kTimeout));
695*8975f5c5SAndroid Build Coastguard Worker 
696*8975f5c5SAndroid Build Coastguard Worker     // If the global fence sync is signaled, then the signal from context2 must also be signaled.
697*8975f5c5SAndroid Build Coastguard Worker     // Note that if sync1 was an EGL_SYNC_FENCE_KHR, this would not necessarily be true.
698*8975f5c5SAndroid Build Coastguard Worker     EGLint value = 0;
699*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync2, EGL_SYNC_STATUS_KHR, &value));
700*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(value, EGL_SIGNALED_KHR);
701*8975f5c5SAndroid Build Coastguard Worker 
702*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(EGL_CONDITION_SATISFIED_KHR, eglClientWaitSyncKHR(display, sync2, 0, 0));
703*8975f5c5SAndroid Build Coastguard Worker 
704*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync1));
705*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync2));
706*8975f5c5SAndroid Build Coastguard Worker 
707*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroySurface(display, drawSurface2));
708*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EGL_TRUE(eglDestroyContext(display, context2));
709*8975f5c5SAndroid Build Coastguard Worker }
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker // Test that leaked fences are cleaned up in a safe way. Regression test for sync objects using tail
712*8975f5c5SAndroid Build Coastguard Worker // calls for destruction.
TEST_P(EGLSyncTest,DISABLED_LeakSyncToDisplayDestruction)713*8975f5c5SAndroid Build Coastguard Worker TEST_P(EGLSyncTest, DISABLED_LeakSyncToDisplayDestruction)
714*8975f5c5SAndroid Build Coastguard Worker {
715*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
716*8975f5c5SAndroid Build Coastguard Worker 
717*8975f5c5SAndroid Build Coastguard Worker     EGLDisplay display = getEGLWindow()->getDisplay();
718*8975f5c5SAndroid Build Coastguard Worker 
719*8975f5c5SAndroid Build Coastguard Worker     EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
720*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(sync, EGL_NO_SYNC_KHR);
721*8975f5c5SAndroid Build Coastguard Worker }
722*8975f5c5SAndroid Build Coastguard Worker 
723*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLSyncTest);
724