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
7 // SyncEGL.cpp: Implements the rx::SyncEGL class.
8
9 #include "libANGLE/renderer/gl/egl/SyncEGL.h"
10
11 #include "libANGLE/AttributeMap.h"
12 #include "libANGLE/Display.h"
13 #include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
14
15 namespace rx
16 {
17
SyncEGL(const FunctionsEGL * egl)18 SyncEGL::SyncEGL(const FunctionsEGL *egl) : mEGL(egl), mSync(EGL_NO_SYNC_KHR) {}
19
~SyncEGL()20 SyncEGL::~SyncEGL()
21 {
22 ASSERT(mSync == EGL_NO_SYNC_KHR);
23 }
24
onDestroy(const egl::Display * display)25 void SyncEGL::onDestroy(const egl::Display *display)
26 {
27 if (mSync != EGL_NO_SYNC_KHR)
28 {
29 egl::Display::GetCurrentThreadUnlockedTailCall()->add(
30 [egl = mEGL, sync = mSync](void *resultOut) {
31 EGLBoolean result = egl->destroySyncKHR(sync);
32 if (resultOut)
33 {
34 // It's possible for resultOut to be null if this sync is being destructed as
35 // part of display destruction.
36 *static_cast<EGLBoolean *>(resultOut) = result;
37 }
38 });
39 mSync = EGL_NO_SYNC_KHR;
40 }
41 }
42
initialize(const egl::Display * display,const gl::Context * context,EGLenum type,const egl::AttributeMap & attribs)43 egl::Error SyncEGL::initialize(const egl::Display *display,
44 const gl::Context *context,
45 EGLenum type,
46 const egl::AttributeMap &attribs)
47 {
48 ASSERT(type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID);
49
50 constexpr size_t kAttribVectorSize = 3;
51 angle::FixedVector<EGLint, kAttribVectorSize> nativeAttribs;
52 if (type == EGL_SYNC_NATIVE_FENCE_ANDROID)
53 {
54 EGLint fenceFd =
55 attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID);
56 nativeAttribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
57 nativeAttribs.push_back(fenceFd);
58 }
59 nativeAttribs.push_back(EGL_NONE);
60
61 egl::Display::GetCurrentThreadUnlockedTailCall()->add(
62 [egl = mEGL, &sync = mSync, type, attribs = nativeAttribs](void *resultOut) {
63 sync = egl->createSyncKHR(type, attribs.data());
64
65 // If sync creation failed, force the return value of eglCreateSync to EGL_NO_SYNC. This
66 // won't delete this sync object but a driver error is unexpected at this point.
67 if (sync == EGL_NO_SYNC_KHR)
68 {
69 ERR() << "eglCreateSync failed with " << gl::FmtHex(egl->getError());
70 *static_cast<EGLSync *>(resultOut) = EGL_NO_SYNC_KHR;
71 }
72 });
73
74 return egl::NoError();
75 }
76
clientWait(const egl::Display * display,const gl::Context * context,EGLint flags,EGLTime timeout,EGLint * outResult)77 egl::Error SyncEGL::clientWait(const egl::Display *display,
78 const gl::Context *context,
79 EGLint flags,
80 EGLTime timeout,
81 EGLint *outResult)
82 {
83 ASSERT(mSync != EGL_NO_SYNC_KHR);
84
85 // If we need to perform a CPU wait don't set the resultOut parameter passed into the
86 // method, instead set the parameter passed into the unlocked tail call.
87 egl::Display::GetCurrentThreadUnlockedTailCall()->add(
88 [egl = mEGL, sync = mSync, flags, timeout](void *resultOut) {
89 *static_cast<EGLint *>(resultOut) = egl->clientWaitSyncKHR(sync, flags, timeout);
90 });
91
92 return egl::NoError();
93 }
94
serverWait(const egl::Display * display,const gl::Context * context,EGLint flags)95 egl::Error SyncEGL::serverWait(const egl::Display *display,
96 const gl::Context *context,
97 EGLint flags)
98 {
99 ASSERT(mSync != EGL_NO_SYNC_KHR);
100
101 egl::Display::GetCurrentThreadUnlockedTailCall()->add(
102 [egl = mEGL, sync = mSync, flags](void *resultOut) {
103 *static_cast<EGLBoolean *>(resultOut) = egl->waitSyncKHR(sync, flags);
104 });
105
106 return egl::NoError();
107 }
108
getStatus(const egl::Display * display,EGLint * outStatus)109 egl::Error SyncEGL::getStatus(const egl::Display *display, EGLint *outStatus)
110 {
111 ASSERT(mSync != EGL_NO_SYNC_KHR);
112 EGLBoolean result = mEGL->getSyncAttribKHR(mSync, EGL_SYNC_STATUS_KHR, outStatus);
113
114 if (result == EGL_FALSE)
115 {
116 return egl::Error(mEGL->getError(), "eglGetSyncAttribKHR with EGL_SYNC_STATUS_KHR failed");
117 }
118
119 return egl::NoError();
120 }
121
dupNativeFenceFD(const egl::Display * display,EGLint * result) const122 egl::Error SyncEGL::dupNativeFenceFD(const egl::Display *display, EGLint *result) const
123 {
124 ASSERT(mSync != EGL_NO_SYNC_KHR);
125 *result = mEGL->dupNativeFenceFDANDROID(mSync);
126 if (*result == EGL_NO_NATIVE_FENCE_FD_ANDROID)
127 {
128 return egl::Error(mEGL->getError(), "eglDupNativeFenceFDANDROID failed");
129 }
130
131 return egl::NoError();
132 }
133
134 } // namespace rx
135