Path: blob/main_old/src/tests/egl_tests/EGLSyncTest.cpp
1693 views
//1// Copyright 2019 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// EGLSyncTest.cpp:6// Tests of EGL_KHR_fence_sync and EGL_KHR_wait_sync extensions.78#include <gtest/gtest.h>910#include "test_utils/ANGLETest.h"11#include "test_utils/angle_test_configs.h"12#include "util/EGLWindow.h"1314using namespace angle;1516class EGLSyncTest : public ANGLETest17{18protected:19bool hasFenceSyncExtension() const20{21return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_fence_sync");22}23bool hasWaitSyncExtension() const24{25return hasFenceSyncExtension() &&26IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_wait_sync");27}28bool hasGLSyncExtension() const { return IsGLExtensionEnabled("GL_OES_EGL_sync"); }2930bool hasAndroidNativeFenceSyncExtension() const31{32return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),33"EGL_ANDROID_native_fence_sync");34}35};3637// Test error cases for all EGL_KHR_fence_sync functions38TEST_P(EGLSyncTest, FenceSyncErrors)39{40ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());4142EGLDisplay display = getEGLWindow()->getDisplay();4344// If the client API doesn't have the necessary extension, test that sync creation fails and45// ignore the rest of the tests.46if (!hasGLSyncExtension())47{48EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr));49EXPECT_EGL_ERROR(EGL_BAD_MATCH);50}5152ANGLE_SKIP_TEST_IF(!hasGLSyncExtension());5354EGLContext context = eglGetCurrentContext();55EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);56EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);5758EXPECT_NE(context, EGL_NO_CONTEXT);59EXPECT_NE(drawSurface, EGL_NO_SURFACE);60EXPECT_NE(readSurface, EGL_NO_SURFACE);6162// CreateSync with no attribute shouldn't cause an error63EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);64EXPECT_NE(sync, EGL_NO_SYNC_KHR);6566EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));6768// CreateSync with empty attribute shouldn't cause an error69const EGLint emptyAttributes[] = {EGL_NONE};70sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, emptyAttributes);71EXPECT_NE(sync, EGL_NO_SYNC_KHR);7273// DestroySync generates BAD_PARAMETER if the sync is not valid74EXPECT_EGL_FALSE(eglDestroySyncKHR(display, reinterpret_cast<EGLSyncKHR>(20)));75EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);7677// CreateSync generates BAD_DISPLAY if display is not valid78EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(EGL_NO_DISPLAY, EGL_SYNC_FENCE_KHR, nullptr));79EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);8081// CreateSync generates BAD_ATTRIBUTE if attribute is neither nullptr nor empty.82const EGLint nonEmptyAttributes[] = {83EGL_CL_EVENT_HANDLE,840,85EGL_NONE,86};87EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nonEmptyAttributes));88EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);8990// CreateSync generates BAD_ATTRIBUTE if type is not valid91EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, 0, nullptr));92EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);9394// CreateSync generates BAD_MATCH if no context is current95eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);96EXPECT_EQ(EGL_NO_SYNC_KHR, eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr));97EXPECT_EGL_ERROR(EGL_BAD_MATCH);98eglMakeCurrent(display, drawSurface, readSurface, context);99100// ClientWaitSync generates EGL_BAD_PARAMETER if the sync object is not valid101EXPECT_EGL_FALSE(eglClientWaitSyncKHR(display, reinterpret_cast<EGLSyncKHR>(30), 0, 0));102EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);103104// GetSyncAttrib generates EGL_BAD_PARAMETER if the sync object is not valid, and value is not105// modified106constexpr EGLint kSentinelAttribValue = 123456789;107EGLint attribValue = kSentinelAttribValue;108EXPECT_EGL_FALSE(eglGetSyncAttribKHR(display, reinterpret_cast<EGLSyncKHR>(40),109EGL_SYNC_TYPE_KHR, &attribValue));110EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);111EXPECT_EQ(attribValue, kSentinelAttribValue);112113// GetSyncAttrib generates EGL_BAD_ATTRIBUTE if the attribute is not valid, and value is not114// modified115EXPECT_EGL_FALSE(eglGetSyncAttribKHR(display, sync, EGL_CL_EVENT_HANDLE, &attribValue));116EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE);117EXPECT_EQ(attribValue, kSentinelAttribValue);118119// GetSyncAttrib generates EGL_BAD_MATCH if the attribute is valid for sync, but not the120// particular sync type. We don't have such a case at the moment.121122EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));123}124125// Test error cases for all EGL_KHR_wait_sync functions126TEST_P(EGLSyncTest, WaitSyncErrors)127{128// The client API that shows support for eglWaitSyncKHR is the same as the one required for129// eglCreateSyncKHR. As such, there is no way to create a sync and not be able to wait on it.130// This would have created an EGL_BAD_MATCH error.131ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());132133EGLDisplay display = getEGLWindow()->getDisplay();134EGLContext context = eglGetCurrentContext();135EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW);136EGLSurface readSurface = eglGetCurrentSurface(EGL_READ);137138EXPECT_NE(context, EGL_NO_CONTEXT);139EXPECT_NE(drawSurface, EGL_NO_SURFACE);140EXPECT_NE(readSurface, EGL_NO_SURFACE);141142EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);143EXPECT_NE(sync, EGL_NO_SYNC_KHR);144145// WaitSync generates BAD_MATCH if no context is current146eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);147EXPECT_EGL_FALSE(eglWaitSyncKHR(display, sync, 0));148EXPECT_EGL_ERROR(EGL_BAD_MATCH);149eglMakeCurrent(display, drawSurface, readSurface, context);150151// WaitSync generates BAD_PARAMETER if the sync is not valid152EXPECT_EGL_FALSE(eglWaitSyncKHR(display, reinterpret_cast<EGLSyncKHR>(20), 0));153EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);154155// WaitSync generates BAD_PARAMETER if flags is non-zero156EXPECT_EGL_FALSE(eglWaitSyncKHR(display, sync, 1));157EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);158159EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));160}161162// Test usage of eglGetSyncAttribKHR163TEST_P(EGLSyncTest, GetSyncAttrib)164{165ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());166167EGLDisplay display = getEGLWindow()->getDisplay();168169EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);170EXPECT_NE(sync, EGL_NO_SYNC_KHR);171172// Fence sync attributes are:173//174// EGL_SYNC_TYPE_KHR: EGL_SYNC_FENCE_KHR175// EGL_SYNC_STATUS_KHR: EGL_UNSIGNALED_KHR or EGL_SIGNALED_KHR176// EGL_SYNC_CONDITION_KHR: EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR177178constexpr EGLint kSentinelAttribValue = 123456789;179EGLint attribValue = kSentinelAttribValue;180EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_TYPE_KHR, &attribValue));181EXPECT_EQ(attribValue, EGL_SYNC_FENCE_KHR);182183attribValue = kSentinelAttribValue;184EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_CONDITION_KHR, &attribValue));185EXPECT_EQ(attribValue, EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR);186187attribValue = kSentinelAttribValue;188EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &attribValue));189190// Hack around EXPECT_* not having an "either this or that" variant:191if (attribValue != EGL_SIGNALED_KHR)192{193EXPECT_EQ(attribValue, EGL_UNSIGNALED_KHR);194}195196EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));197}198199// Test that basic usage works and doesn't generate errors or crash200TEST_P(EGLSyncTest, BasicOperations)201{202ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());203204EGLDisplay display = getEGLWindow()->getDisplay();205206EGLSyncKHR sync = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);207EXPECT_NE(sync, EGL_NO_SYNC_KHR);208209glClearColor(1.0f, 0.0f, 1.0f, 1.0f);210211glClear(GL_COLOR_BUFFER_BIT);212EXPECT_EGL_TRUE(eglWaitSyncKHR(display, sync, 0));213214glFlush();215216glClear(GL_COLOR_BUFFER_BIT);217218// Don't wait forever to make sure the test terminates219constexpr GLuint64 kTimeout = 1'000'000'000; // 1 second220EGLint value = 0;221ASSERT_EQ(EGL_CONDITION_SATISFIED_KHR,222eglClientWaitSyncKHR(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, kTimeout));223224for (size_t i = 0; i < 20; i++)225{226glClear(GL_COLOR_BUFFER_BIT);227EXPECT_EQ(228EGL_CONDITION_SATISFIED_KHR,229eglClientWaitSyncKHR(display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR));230EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, sync, EGL_SYNC_STATUS_KHR, &value));231EXPECT_EQ(value, EGL_SIGNALED_KHR);232}233234EXPECT_EGL_TRUE(eglDestroySyncKHR(display, sync));235}236237// Test eglWaitClient api238TEST_P(EGLSyncTest, WaitClient)239{240// Clear to red color241glClearColor(1.0f, 0.0f, 0.0f, 1.0f);242243glClear(GL_COLOR_BUFFER_BIT);244EXPECT_EGL_TRUE(eglWaitClient());245EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);246247EGLDisplay display = getEGLWindow()->getDisplay();248EGLContext context = getEGLWindow()->getContext();249EGLSurface surface = getEGLWindow()->getSurface();250eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);251EXPECT_EGL_TRUE(eglWaitClient());252eglMakeCurrent(display, surface, surface, context);253}254255// Test eglWaitGL api256TEST_P(EGLSyncTest, WaitGL)257{258// Clear to red color259glClearColor(1.0f, 0.0f, 0.0f, 1.0f);260261glClear(GL_COLOR_BUFFER_BIT);262EXPECT_EGL_TRUE(eglWaitGL());263EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);264265EGLDisplay display = getEGLWindow()->getDisplay();266EGLContext context = getEGLWindow()->getContext();267EGLSurface surface = getEGLWindow()->getSurface();268eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);269EXPECT_EGL_TRUE(eglWaitGL());270eglMakeCurrent(display, surface, surface, context);271}272273// Test eglWaitNative api274TEST_P(EGLSyncTest, WaitNative)275{276// Clear to red color277glClearColor(1.0f, 0.0f, 0.0f, 1.0f);278279glClear(GL_COLOR_BUFFER_BIT);280EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));281EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);282283EGLDisplay display = getEGLWindow()->getDisplay();284EGLContext context = getEGLWindow()->getContext();285EGLSurface surface = getEGLWindow()->getSurface();286eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);287EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));288eglMakeCurrent(display, surface, surface, context);289}290291// Verify eglDupNativeFence for EGL_ANDROID_native_fence_sync292TEST_P(EGLSyncTest, AndroidNativeFence_DupNativeFenceFD)293{294ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());295ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());296ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());297298EGLDisplay display = getEGLWindow()->getDisplay();299300// We can ClientWait on this301EGLSyncKHR syncWithGeneratedFD =302eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);303EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);304305int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD);306EXPECT_EGL_SUCCESS();307308// Clean up created objects.309if (fd != EGL_NO_NATIVE_FENCE_FD_ANDROID)310{311close(fd);312}313314EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));315}316317// Verify CreateSync and ClientWait for EGL_ANDROID_native_fence_sync318TEST_P(EGLSyncTest, AndroidNativeFence_ClientWait)319{320ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());321ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension());322ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());323324EGLint value = 0;325EGLDisplay display = getEGLWindow()->getDisplay();326327// We can ClientWait on this328EGLSyncKHR syncWithGeneratedFD =329eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);330EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);331332// Create work to do333glClearColor(0.0f, 1.0f, 0.0f, 1.0f);334glClear(GL_COLOR_BUFFER_BIT);335glFlush();336337// Wait for draw to complete338EXPECT_EQ(EGL_CONDITION_SATISFIED,339eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,3401000000000));341EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));342EXPECT_EQ(value, EGL_SIGNALED_KHR);343344// Clean up created objects.345EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));346}347348// Verify WaitSync with EGL_ANDROID_native_fence_sync349// Simulate passing FDs across processes by passing across Contexts.350TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)351{352ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());353ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());354ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());355356EGLint value = 0;357EGLDisplay display = getEGLWindow()->getDisplay();358EGLSurface surface = getEGLWindow()->getSurface();359360/*- First Context ------------------------*/361362// We can ClientWait on this363EGLSyncKHR syncWithGeneratedFD =364eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);365EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);366367int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD);368EXPECT_EGL_SUCCESS(); // Can return -1 (when signaled) or valid FD.369370// Create work to do371glClearColor(0.0f, 1.0f, 0.0f, 1.0f);372glClear(GL_COLOR_BUFFER_BIT);373glFlush();374375/*- Second Context ------------------------*/376if (fd > EGL_NO_NATIVE_FENCE_FD_ANDROID)377{378EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));379380EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT);381EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2));382383// We can eglWaitSync on this - import FD from first sync.384EGLint syncAttribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, (EGLint)fd, EGL_NONE};385EGLSyncKHR syncWithDupFD =386eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, syncAttribs);387EXPECT_NE(syncWithDupFD, EGL_NO_SYNC_KHR);388389// Second draw waits for first to complete. May already be signaled - ignore error.390if (eglWaitSyncKHR(display, syncWithDupFD, 0) == EGL_TRUE)391{392// Create work to do393glClearColor(1.0f, 0.0f, 0.0f, 1.0f);394glClear(GL_COLOR_BUFFER_BIT);395glFlush();396}397398// Wait for second draw to complete399EXPECT_EQ(EGL_CONDITION_SATISFIED,400eglClientWaitSyncKHR(display, syncWithDupFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,4011000000000));402EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithDupFD, EGL_SYNC_STATUS_KHR, &value));403EXPECT_EQ(value, EGL_SIGNALED_KHR);404405// Reset to default context and surface.406EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));407EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, getEGLWindow()->getContext()));408409// Clean up created objects.410EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithDupFD));411EXPECT_EGL_TRUE(eglDestroyContext(display, context2));412}413414// Wait for first draw to complete415EXPECT_EQ(EGL_CONDITION_SATISFIED,416eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,4171000000000));418EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));419EXPECT_EQ(value, EGL_SIGNALED_KHR);420421// Clean up created objects.422EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));423}424425// Verify EGL_ANDROID_native_fence_sync426// Simulate passing FDs across processes by passing across Contexts.427TEST_P(EGLSyncTest, AndroidNativeFence_withFences)428{429ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());430ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());431ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());432433EGLint value = 0;434EGLDisplay display = getEGLWindow()->getDisplay();435EGLSurface surface = getEGLWindow()->getSurface();436437/*- First Context ------------------------*/438439// Extra fence syncs to ensure that Fence and Android Native fences work together440EGLSyncKHR syncFence1 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);441EXPECT_NE(syncFence1, EGL_NO_SYNC_KHR);442443// We can ClientWait on this444EGLSyncKHR syncWithGeneratedFD =445eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);446EXPECT_NE(syncWithGeneratedFD, EGL_NO_SYNC_KHR);447448int fd = eglDupNativeFenceFDANDROID(display, syncWithGeneratedFD);449EXPECT_EGL_SUCCESS(); // Can return -1 (when signaled) or valid FD.450451EGLSyncKHR syncFence2 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);452EXPECT_NE(syncFence2, EGL_NO_SYNC_KHR);453454// Create work to do455glClearColor(0.0f, 1.0f, 0.0f, 1.0f);456glClear(GL_COLOR_BUFFER_BIT);457glFlush();458459/*- Second Context ------------------------*/460if (fd > EGL_NO_NATIVE_FENCE_FD_ANDROID)461{462EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));463464EGLContext context2 = getEGLWindow()->createContext(EGL_NO_CONTEXT);465EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, context2));466467// check that Fence and Android fences work together468EGLSyncKHR syncFence3 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);469EXPECT_NE(syncFence3, EGL_NO_SYNC_KHR);470471// We can eglWaitSync on this472EGLint syncAttribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, (EGLint)fd, EGL_NONE};473EGLSyncKHR syncWithDupFD =474eglCreateSyncKHR(display, EGL_SYNC_NATIVE_FENCE_ANDROID, syncAttribs);475EXPECT_NE(syncWithDupFD, EGL_NO_SYNC_KHR);476477EGLSyncKHR syncFence4 = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);478EXPECT_NE(syncFence4, EGL_NO_SYNC_KHR);479480// Second draw waits for first to complete. May already be signaled - ignore error.481if (eglWaitSyncKHR(display, syncWithDupFD, 0) == EGL_TRUE)482{483// Create work to do484glClearColor(1.0f, 0.0f, 0.0f, 1.0f);485glClear(GL_COLOR_BUFFER_BIT);486glFlush();487}488489// Wait for second draw to complete490EXPECT_EQ(EGL_CONDITION_SATISFIED,491eglClientWaitSyncKHR(display, syncWithDupFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,4921000000000));493EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithDupFD, EGL_SYNC_STATUS_KHR, &value));494EXPECT_EQ(value, EGL_SIGNALED_KHR);495496// Reset to default context and surface.497EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));498EXPECT_EGL_TRUE(eglMakeCurrent(display, surface, surface, getEGLWindow()->getContext()));499500// Clean up created objects.501EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence3));502EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence4));503EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithDupFD));504EXPECT_EGL_TRUE(eglDestroyContext(display, context2));505}506507// Wait for first draw to complete508EXPECT_EQ(EGL_CONDITION_SATISFIED,509eglClientWaitSyncKHR(display, syncWithGeneratedFD, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,5101000000000));511EXPECT_EGL_TRUE(eglGetSyncAttribKHR(display, syncWithGeneratedFD, EGL_SYNC_STATUS_KHR, &value));512EXPECT_EQ(value, EGL_SIGNALED_KHR);513514// Clean up created objects.515EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence1));516EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncFence2));517EXPECT_EGL_TRUE(eglDestroySyncKHR(display, syncWithGeneratedFD));518}519520ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLSyncTest);521522523