xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/egl/SyncEGL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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