1 //
2 // Copyright 2020 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 // EGLReusableSync.cpp: Implements the egl::ReusableSync class.
8
9 #include "libANGLE/renderer/EGLReusableSync.h"
10
11 #include "libANGLE/Context.h"
12 #include "libANGLE/renderer/ContextImpl.h"
13
14 namespace rx
15 {
16
ReusableSync(const egl::AttributeMap & attribs)17 ReusableSync::ReusableSync(const egl::AttributeMap &attribs)
18 : EGLSyncImpl(), mStatus(EGL_UNSIGNALED)
19 {}
20
onDestroy(const egl::Display * display)21 void ReusableSync::onDestroy(const egl::Display *display) {}
22
~ReusableSync()23 ReusableSync::~ReusableSync()
24 {
25 // Release any waiting thread.
26 mCondVar.notify_all();
27 }
28
initialize(const egl::Display * display,const gl::Context * context,EGLenum type)29 egl::Error ReusableSync::initialize(const egl::Display *display,
30 const gl::Context *context,
31 EGLenum type)
32 {
33 return egl::NoError();
34 }
35
clientWait(const egl::Display * display,const gl::Context * context,EGLint flags,EGLTime timeout,EGLint * outResult)36 egl::Error ReusableSync::clientWait(const egl::Display *display,
37 const gl::Context *context,
38 EGLint flags,
39 EGLTime timeout,
40 EGLint *outResult)
41 {
42 if (mStatus == EGL_SIGNALED)
43 {
44 *outResult = EGL_CONDITION_SATISFIED_KHR;
45 return egl::NoError();
46 }
47 if (((flags & EGL_SYNC_FLUSH_COMMANDS_BIT) != 0) && (context != nullptr))
48 {
49 angle::Result result = context->getImplementation()->flush(context);
50 if (result != angle::Result::Continue)
51 {
52 return ResultToEGL(result);
53 }
54 }
55 if (timeout == 0)
56 {
57 *outResult = EGL_TIMEOUT_EXPIRED_KHR;
58 return egl::NoError();
59 }
60
61 using NanoSeconds = std::chrono::duration<int64_t, std::nano>;
62 NanoSeconds duration = (timeout == EGL_FOREVER) ? NanoSeconds::max() : NanoSeconds(timeout);
63 std::cv_status waitStatus = std::cv_status::no_timeout;
64 mMutex.lock();
65 waitStatus = mCondVar.wait_for(mMutex, duration);
66 mMutex.unlock();
67
68 switch (waitStatus)
69 {
70 case std::cv_status::no_timeout: // Signaled.
71 *outResult = EGL_CONDITION_SATISFIED_KHR;
72 break;
73 case std::cv_status::timeout: // Timed-out.
74 *outResult = EGL_TIMEOUT_EXPIRED_KHR;
75 break;
76 default:
77 break;
78 }
79 return egl::NoError();
80 }
81
serverWait(const egl::Display * display,const gl::Context * context,EGLint flags)82 egl::Error ReusableSync::serverWait(const egl::Display *display,
83 const gl::Context *context,
84 EGLint flags)
85 {
86 // Does not support server wait.
87 return egl::EglBadMatch();
88 }
89
signal(const egl::Display * display,const gl::Context * context,EGLint mode)90 egl::Error ReusableSync::signal(const egl::Display *display,
91 const gl::Context *context,
92 EGLint mode)
93 {
94 if (mode == EGL_SIGNALED)
95 {
96 if (mStatus == EGL_UNSIGNALED)
97 {
98 // Release all threads.
99 mCondVar.notify_all();
100 }
101 mStatus = EGL_SIGNALED;
102 }
103 else
104 {
105 mStatus = EGL_UNSIGNALED;
106 }
107 return egl::NoError();
108 }
109
getStatus(const egl::Display * display,EGLint * outStatus)110 egl::Error ReusableSync::getStatus(const egl::Display *display, EGLint *outStatus)
111 {
112 *outStatus = mStatus;
113 return egl::NoError();
114 }
115
116 } // namespace rx
117